gpt4 book ai didi

c++ - 将值从 CSV 文件存储到动态 char 数组

转载 作者:行者123 更新时间:2023-12-01 14:48:06 25 4
gpt4 key购买 nike

我正在尝试从 CSV 文件中存储某些值,该文件在动态 char 数组中包含以下详细信息。我能够阅读 CSV 文件,并在下面的描述中提供了代码。如果有人可以让我知道我应该使用什么方法将CSV中的一行中的某些数据存储在动态char数组中,我将不胜感激。谢谢!我还编写了一个子字符串函数,它通过放置起始索引、结束索引和源的参数来返回特定的字符串。

CSV 文件:-
地点,名称,纬度,经度,1/22/20,1/23/20,1/24/20
我想将 Long 之后的日期(不带逗号)存储在动态 char 数组中(我不能使用 vector )谢谢!

char* substring(char* source, int startIndex, int endIndex)
{
int size = endIndex - startIndex + 1;
char* s = new char[size+1];
strncpy(s, source + startIndex, size);
s[size] = '\0'; //make it null-terminated
return s;
}

char** readCSV(const char* csvFileName, int& csvLineCount)
{
ifstream fin(csvFileName);
if (!fin)
{
return nullptr;
}
csvLineCount = 0;
char line[1024];

最佳答案

根据您的评论,您仍然在动态分配从 csv 文件读取的行时遇到问题(并且需要注意的是,今天的程序应该避免使用旧的指向 char 的指针,而使用字符串 vector )——一个原因是您正在以低效的方式处理指针分配。不是单次遍历输入文件,而是遍历文件两次,一次读取行数(分配指针),然后再次读取并为每一行分配存储空间。虽然这是一种方法 - 这是一种非常低效的方法,因为文件 I/O 是您可以执行的效率最低的任务之一(并且您执行了两次)

相反,只需分配一些初始数量的指针(1 或 2 或 8 是一个很好的起点)。然后,您跟踪可用的已分配指针的数量(例如 size_t avail = 2; 和使用的指针数量(例如 size_t used = 0; )。然后,当您阅读行时,您检查 if (used == available) 以了解何时重新分配更多指针。您可以使用临时 char** 指针简单地重新分配当前指针数量的 2 倍。然后将现有指针复制到 tmpdelete[] lines;,然后将包含指针的新内存块分配回 lines .

另一个改变是打开你的std::ifstream main() 中的文件流,验证它是否打开以供读取,然后将对打开流的引用作为参数传递给您的函数,而不是传递文件名(如果您无法在调用者中成功打开流 - 无需进行函数调用来计算行数)

要从处理分配的流中读取行,您可以执行以下操作:

#include <iostream>
#include <fstream>
#include <cstring>

#define MAXC 1024

char **readcsv (std::ifstream& fin, size_t& csvLineCount)
{
size_t avail = 2, used = 0; /* allocated/used counters */
char line[MAXC], **lines = new char*[avail]; /* line and lines */

while (fin.getline (line, MAXC)) { /* loop reading each line */
size_t len; /* for line length */
if (used == avail) { /* all pointers used? */
char **tmp = new char *[2 * avail]; /* allocate twice as many */
memcpy (tmp, lines, used * sizeof *lines); /* copy lines to new tmp */
delete[] lines; /* free existing pionters */
lines = tmp; /* set lines to new block */
avail *= 2; /* update ptrs available */
}
lines[used] = new char[(len = strlen(line)) + 1]; /* alloc for lines[used] */
memcpy (lines[used++], line, len + 1); /* copy line to lines[used] */
}
csvLineCount = used; /* update csvLineCount to used */

return lines; /* return lines */
}

加短 main()它将要读取的文件名作为程序的第一个参数并在 main() 中打开流在将对打开流的引用传递给您的读取函数之前:
int main (int argc, char **argv) {

if (argc < 2) { /* validate 1 argument given for filename */
std::cerr << "error: insufficient input.\n"
"usage: " << argv[0] << " filename.\n";
return 1;
}

char **lines = nullptr; /* pointer-to-pointer to char */
size_t nlines = 0; /* line counter */
std::ifstream f (argv[1]); /* file stream */

if (!f.is_open()) { /* validate file open for reading */
std::cerr << "error: file open failed '" << argv[1] << "'.\n";
return 1;
}

if (!(lines = readcsv (f, nlines))) { /* call line read function/validate */
std::cerr << "error: readcsv() failed.\n";
return 1;
}

for (size_t i = 0; i < nlines; i++) { /* loop outputting lines, freeing memory */
std::cout << lines[i] << '\n';
delete[] lines[i]; /* free lines */
}
delete[] lines; /* free pointers */
}

示例输入文件
$ cat dat/latlon.csv
place1,name1,Lat1,Long1,1/22/20,1/23/20,1/24/20
place2,name2,Lat2,Long2,1/22/20,1/23/20,1/24/20
place3,name3,Lat3,Long3,1/22/20,1/23/20,1/24/20
place4,name4,Lat4,Long4,1/22/20,1/23/20,1/24/20

示例使用/输出

所有行成功存储在分配的内存中:
$ ./bin/read_alloc_csv_lines dat/latlon.csv
place1,name1,Lat1,Long1,1/22/20,1/23/20,1/24/20
place2,name2,Lat2,Long2,1/22/20,1/23/20,1/24/20
place3,name3,Lat3,Long3,1/22/20,1/23/20,1/24/20
place4,name4,Lat4,Long4,1/22/20,1/23/20,1/24/20

内存使用/错误检查

在您编写的任何动态分配内存的代码中,对于分配的任何内存块,您有 2 个责任:(1)始终保留指向内存块起始地址的指针,(2)它可以在它不存在时被释放更需要。

您必须使用内存错误检查程序,以确保您不会尝试访问内存或写入超出/超出分配 block 的范围,尝试读取或基于未初始化值的条件跳转,最后确认释放所有分配的内存。

对于 Linux valgrind是正常的选择。每个平台都有类似的内存检查器。它们都易于使用,只需通过它运行您的程序即可。
$ valgrind ./bin/read_alloc_csv_lines dat/latlon.csv
==8108== Memcheck, a memory error detector
==8108== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==8108== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==8108== Command: ./bin/read_alloc_csv_lines dat/latlon.csv
==8108==
place1,name1,Lat1,Long1,1/22/20,1/23/20,1/24/20
place2,name2,Lat2,Long2,1/22/20,1/23/20,1/24/20
place3,name3,Lat3,Long3,1/22/20,1/23/20,1/24/20
place4,name4,Lat4,Long4,1/22/20,1/23/20,1/24/20
==8108==
==8108== HEAP SUMMARY:
==8108== in use at exit: 0 bytes in 0 blocks
==8108== total heap usage: 10 allocs, 10 frees, 82,712 bytes allocated
==8108==
==8108== All heap blocks were freed -- no leaks are possible
==8108==
==8108== For counts of detected and suppressed errors, rerun with: -v
==8108== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

始终确认您已释放所有已分配的内存并且没有内存错误。

由于您的评论涉及将行读取到分配的内存中的问题,因此我已将子字符串留给您处理。如果您以后有问题,请告诉我。如果您对上述事情的完成方式有任何进一步的疑问,也请告诉我。

关于c++ - 将值从 CSV 文件存储到动态 char 数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61356961/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com