将sprintf更改为字符数组C++



我有一个2d单词数组。

void main() {
const int rowsCount = 2;
const int colsCount = 5;
char*** szData = new char** [rowsCount];
//Allocate memory for each row
for (int i = 0; i < rowsCount; i++)
{
szData[i] = new char* [colsCount]; //how many words in every row
for (int j = 0; j < colsCount; j++)
{
szData[i][j] = new char[15]; //maximum symbols in a word
}
}
//Assign some data
for (int i = 0; i < rowsCount; i++)
{
char s[] = "Williams";
szData[i][0] = s;
sprintf(szData[i][0], "Williams%d", 0);
sprintf(szData[i][1], "J.%d", 0);
sprintf(szData[i][2], "#3%d", 0);
sprintf(szData[i][3], "100%d", 0);
sprintf(szData[i][4], "01.13%d", 0);
}
...
}

在分配数据时,我试图更改这个

sprintf(szData[i][0], "Williams%d");

到这个

char s[] = "Williams";
szData[i][0] = s;

为什么我一直收到这样的信息:我的项目";触发了断点";?

除了使用字符数组的sprintf,还有其他选择吗?无法使用string(此任务的条件之一(

同样,没有那么必要,但如果我在这里删除末尾的0

sprintf(szData[i][0], "Williams%d", 0);
sprintf(szData[i][1], "J.%d", 0);
sprintf(szData[i][2], "#3%d", 0);
sprintf(szData[i][3], "100%d", 0);
sprintf(szData[i][4], "01.13%d", 0);

每个单词后面都会出现一些数字。例如:Williams3937516。为什么?

完整代码:

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <iomanip>
#include <conio.h> 
using namespace std;
void main() {
const int rowsCount = 2;
const int colsCount = 5;
char*** szData = new char** [rowsCount];
//Allocate memory for each row
for (int i = 0; i < rowsCount; i++)
{
szData[i] = new char* [colsCount]; //how many words in every row
for (int j = 0; j < colsCount; j++)
{
szData[i][j] = new char[15]; //maximum symbols in a word
}
}
//Assign some data
for (int i = 0; i < rowsCount; i++)
{
char s[] = "Williams";
szData[i][0] = s;
sprintf(szData[i][0], "Williams%d");
sprintf(szData[i][1], "J.%d", 0);
sprintf(szData[i][2], "#3%d", 0);
sprintf(szData[i][3], "100%d", 0);
sprintf(szData[i][4], "01.13%d", 0);
}
//print all the elements
for (int i = 0; i < rowsCount; i++)
{
for (int j = 0; j < colsCount; j++)
{
cout << szData[i][j] << " ";
}
cout << endl;
}
//free memory here
for (int i = 0; i < rowsCount; i++)
{
for (int j = 0; j < colsCount; j++)
{
delete[] szData[i][j];
}
}
for (int i = 0; i < rowsCount; i++)
{
delete[] szData[i];
}
delete[] szData;
}

如果您追溯此指针的赋值:

char s[] = "Williams";

你会发现你正试图在这里释放它的内存:

delete[] szData[i][j];

但是,您不能这样做——字符串"Williams"从来没有用new分配过,所以它不能用delete释放。事实上,它是静态分配的,在二进制文件中。所以堆会抱怨,这就是断点的原因。

如果要将szData中的所有内容都分配给delete,则需要确保所有内容都已在具有new的堆中分配。

第二个问题-当你打电话时:

sprintf(szData[i][0], "Williams%d", 0);

您正在覆盖您提供的内存的边界。请记住,您的缓冲区只有"Williams"字节数(加一(!你没有空间在它的末尾加上一个整数的字符串表示。使用sprintf_s并确保缓冲区有足够的空间!

第三个问题——写入静态分配的字符串数据非常粗略,可能不适用于所有情况。

一句话:动态地为所有内容分配一个合适大小的缓冲区,您的代码就可以工作了。

这里有一个简单的例子来修复这段代码。它展示了修复代码的概念,但它并不真正适合您的代码库,因此您需要正确地使用它。

const size_t MAX_NAME_LENGTH = 15; // Fix this magic number to be whatever max name length you want
char *s = new char[MAX_NAME_LENGTH];  // allocate on heap
strcpy_s(s, MAX_NAME_LENGTH, "Williams");  // use strcpy_s for safety

szData[i][0] = s;
sprintf_s(szData[i][0], MAX_NAME_LENGTH, "Williams%d", 0);  // use sprintf_s for safety

相关内容

  • 没有找到相关文章

最新更新