【问题标题】:How to convert my malloc + strcpy to strdup in C?如何在 C 中将我的 malloc + strcpy 转换为 strdup?
【发布时间】:2014-01-04 18:06:36
【问题描述】:

我正在尝试将 csv 数据保存在一个数组中以供其他函数使用。我知道 strdup 对此有好处,但我不确定如何让它适合我的情况。任何帮助表示赞赏!

数据存储在结构中:

typedef struct current{
    char **data;
}CurrentData;

函数调用:

int main(void){
    int totalProducts = 0;
    CurrentData *AllCurrentData = { '\0' };
    FILE *current = fopen("C:\\User\\myfile.csv", "r");

    if (current == NULL){
        puts("current file data not found");
    }
    else{
        totalProducts = getCurrentData(current, &AllCurrentData);
    }
 fclose(current);
 return 0;
 }

我是如何分配内存的;

 int getCurrentData(FILE *current, CurrentData **AllCurrentData){

*AllCurrentData = malloc(totalProducts * sizeof(CurrentData));

    /*allocate struct data memory*/
    while ((next = fgetc(current)) != EOF){                                                 
        if (next == '\n'){
            (*AllCurrentData)[newLineCount].data = malloc(colCount * sizeof(char*));
            newLineCount++;
        }
    }
    newLineCount = 0;
    rewind(current);

    while ((next = fgetc(current)) != EOF && newLineCount <= totalProducts){                    

        if (ch != '\0'){
            buffer[i] = ch;
            i++;
            characterCount++;
        }

        if (ch == ',' && next != ' ' || ch == '\n' && ch != EOF){
            if (i > 0){
                buffer[i - 1] = '\0';
            }
            length = strlen(buffer);
            /*(*AllCurrentData)[newLineCount].data[tabCount] = malloc(length +  1);     /* originally was using strcpy */
            strcpy((*AllCurrentData)[newLineCount].data[tabCount], buffer);
            */
            (*AllCurrentData)[newLineCount].data[tabCount] = strdup(buffer);  /* something like this? */

            i = 0;
            tabCount++;

            for (j = 0; j < BUFFER_SIZE; j++){
                buffer[j] = '\0';
            }
        }

【问题讨论】:

  • 这不是完整的代码。您有几个未声明或设置的变量。无法从这些片段中准确判断代码在做什么。也不清楚 CurrentData 类型应该包含什么。
  • 看起来您想要做的是打开一个包含文本行的文件,在本例中为逗号分隔值文本,并将每一行读入字符串缓冲区数组,其中每个数组元素指向到包含文本字符串的已分配内存区域。结果应该是一个指向字符串的指针数组,其中字符串的顺序与文件中行的顺序相同。所以 array[0] 应该指向一个缓冲区,该缓冲区包含文件中第一行文本的文本。这是你想做的吗?
  • 乍一看,strdup 不是你的问题;你真正的问题是详尽的分配。例如,您将文件传递两次并计算第一次传递中的换行符。这很好,但是你不知道分配多少,为什么还要在那之前分配呢?

标签: c string strdup


【解决方案1】:

您定义了一个指针 AllCurrentData,但您应该将其设置为 NULL。

CurrentData* AllCurrentData = NULL;

getCurrentData 你使用totalProducts 这似乎有点 奇怪,因为它是 main() 中的局部变量,要么你有另一个 全局变量同名或出错。

结构中的**data 看起来很奇怪,但也许你想要 解析 csv 行并为它们创建适当的成员。你已 有一个 CurrentData 数组,所以有另一个数组似乎很奇怪 在结构内部——我只是在猜测,因为你没有解释 那部分。

由于 csv 文件是基于行的,因此使用 fgets() 读取一行 从文件中,然后使用例如解析字符串strtok 或只是通过 检查分隔符后的缓冲区。这里 strdup 可以发挥作用, 取出令牌后,对其进行 strdup 并将其存储在您的 结构。

char line[255];
if ( fgets(line,sizeof(line),current) != NULL )
{
  char* token = strdup(strtok( line, "," ));
  ...
}

而不是分配一个可能足够(或不够)使用的大缓冲区 realloc 以在您从文件中读取时增加缓冲区。

也就是说,有更快的方法从 csv 文件中提取数据,例如 您可以使用 fread 读取整个文件,然后查找分隔符 并将它们设置为 \0 并在缓冲区中创建一个 char 指针数组。

【讨论】:

  • 感谢csv数据提取的提示,我想我会用你建议的方法重写程序。
【解决方案2】:

好的,我不会评论您代码的其他部分,但是您可以使用 strdup 删除这行 (*AllCurrentData)[newLineCount].data = malloc(colCount * sizeof(char*)); 和这行 (*AllCurrentData)[newLineCount].data[tabCount] = strdup(buffer); /* something like this? */ 并将它们替换为:(*AllCurrentData)[newLineCount].data = strdup(buffer);

【讨论】:

    【解决方案3】:

    对于读取字符串数组的函数,我将从以下方法开始。这尚未经过测试甚至编译,但它是一个起点。

    此示例未解决许多问题。 4K 字符的临时缓冲区大小可能对文件中的所有行都足够大,也可能不够大。文件中的文本行数可能多于指针数组中的元素,并且函数没有表明发生了这种情况。

    对此的改进将是更好的错误处理。也可以对其进行修改,以便在函数中分配大量指针数组,然后如果文件中的行数多于数组元素,则使用 realloc() 函数将指针数组扩大一些大小。也许还可以检查文件大小并使用平均文本行长度来为指针数组提供初始大小。

    // Read lines of text from a text file returning the number of lines.
    // The caller will provide an array of char pointers which will be used
    // to return the list of lines of text from the file.
    int GetTextLines (FILE *hFile, char **pStringArrays, int nArrayLength)
    {
        int  iBuffSize = 4096;
        int  iLineCount = 0;
        char tempBuffer [4096];
    
        while (fgets (tempBuffer, iBuffSize, hFile) && iLineCount < nArrayLength) {
            pStringArrays[iLineCount] = malloc ((strlen(tempBuffer) + 1) * sizeof (char));
            if (! pStringArrays[iLineCount])
                break;
            strcpy (pStringArrays[iLineCount], tempBuffer);
            iLineCount++; 
        }
        return iLineCount;
    }
    

    【讨论】:

      猜你喜欢
      • 2011-08-19
      • 2012-12-10
      • 1970-01-01
      • 2015-03-29
      • 1970-01-01
      • 2017-10-01
      • 2014-08-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多