将 sprintf 更改为字符数组 C++
Changing sprintf to an array of characters C++
我有一个二维单词数组。
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
释放它。事实上,它是在您的二进制文件中静态分配的。所以堆抱怨,这就是断点的原因。
如果您要 delete
szData
中的所有内容,您需要确保它们都分配在 new
的堆上。
第二个问题-当你打电话时:
sprintf(szData[i][0], "Williams%d", 0);
您正在覆盖您提供的内存范围。请记住,您的缓冲区只有 "Williams"
个字节(加一)!您没有 space 在其末尾添加整数的字符串表示形式。使用 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
我有一个二维单词数组。
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
释放它。事实上,它是在您的二进制文件中静态分配的。所以堆抱怨,这就是断点的原因。
如果您要 delete
szData
中的所有内容,您需要确保它们都分配在 new
的堆上。
第二个问题-当你打电话时:
sprintf(szData[i][0], "Williams%d", 0);
您正在覆盖您提供的内存范围。请记住,您的缓冲区只有 "Williams"
个字节(加一)!您没有 space 在其末尾添加整数的字符串表示形式。使用 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