我试图将从stdin
读取的字符串中的值直接写入数组,但是我遇到了分段错误。因为我在读取N和M之后声明了数组,所以应该已经分配了内存,对吧?
int main()
{
long long N;
long long M;
scanf("%lld%lld",&N,&M);
char line[M];
long long map[N][M];
for (long long i=0; i<M; i++)
{
scanf("%s", &line);
buildMap(&map, i, &line);
}
for (long long i=0; i<N; i++)
for (long long j=0; j<M; j++)
printf(&map);
}
void buildMap(long long **map, long long i, char * line)
{
for (long long j=0; j<strlen(line); j++)
{
map[i][j] = line[j]-'0';
}
答案 0 :(得分:1)
请记住,C支持可变长度数组(您已经使用过的数据)。这意味着您实际上可以将维度作为参数传递给函数,并在数组参数的声明中使用它们。也许像是
void buildMap(const size_t N, const size_t M, long long map[N][M], long long i, char * line) { ... }
像
一样打电话buildMap(N, M, map, i, line);
请注意,我已将N
和M
的类型更改为size_t
,这是用于可变长度数组维度的正确类型。您应该相应地更新变量声明,并对scanf
格式字符串使用"%zu
。
请注意,在调用buildMap
时,我不对数组使用address-of运算符。那是因为数组自然地衰减到指向第一个元素的指针。通过,例如&line
在语义上不正确,因为它会将char (*)[M]
类型的内容传递给函数,而不是char *
。
答案 1 :(得分:1)
我已经阅读了您的代码,我假设您正在尝试通过用户输入构建2D地图,这是一个字符串(代码中名为“Line”),应该只包含0到9之间的数字。来自0的数字到9可以表示地图的不同元素。我猜对了吗?
我复制并修改了你的代码,最后我设法得到了这样的结果:
如果我猜对了,请先解释一下您的代码无法成功遵守的原因。
long long M; char line[M];
在这里,您使用了一个变量来声明数组的大小。此语法适用于其他一些编程语言,但不适用于C.在C中,编译源代码时,编译器必须确切地知道为每个函数(在您的情况下为main()函数)分配多少堆栈内存空间。由于编译器在尝试编译代码时不知道数组的大小,因此会出现编译失败。
一个常见的解决方案是,我们选择将数组存储在堆中,而不是将数组存储在堆中,因为堆内存是在程序运行时动态分配和释放的。换句话说,您可以在获得用户输入后决定分配多少内存。函数malloc()和free()用于此类操作。
另一个问题是使用“long long ** map”。虽然它不会导致complie失败,但它也不会给你预期的结果。当数组的M(数组宽度)是已知的常数值时,我们总是使用“long long map [] [M]”作为参数。但是,在你的情况下,M是未知的,通常的解决方案是手动计算目标位置,因为数组中的元素总是以线性顺序存储在内存中,而不管数组的维数是什么。
我已经解决了上述两个问题,我正在粘贴下面修改过的源代码,该代码已成功编译:
#include <malloc.h>
#include <string.h>
void buildMap(int *map, int i, char * line);
int main()
{
int N;
int M;
scanf("%d%d", &N, &M);
/*Since M (available memory space for "Line") is set by user, we need to build
"szSafeFormat" to restrict the user's input when typing the "Line". Assuming M
is set to 8, then "szSafeFormat" will look like "%7s". With the help of
"szSafeFormat", the scanf function will be scanf("%7s", Line), ignoring
characters after offset 7.*/
char szSafeFormat[256] = { 0 };
sprintf(szSafeFormat, "%%%ds", M - 1);
//char line[M];
char *Line = (char *)malloc(sizeof(char) * M); //raw user input
char *pszValidInput = (char *)malloc(sizeof(char) * M); //pure numbers
//long long map[N][M];
int *pnMap = (int *)malloc(sizeof(int) * M * N);
memset(pnMap, 0xFF, M * N * sizeof(int)); //initialize the Map with 0xFF
for (int i = 0; i < /*M*/N; i++)
{
scanf(szSafeFormat, Line); //get raw user input
sscanf(Line, "%[0-9]", pszValidInput); //only accept the numbers
while (getchar() != '\n'); //empty the stdin buffer
buildMap((int *)(pnMap + i * M), i, pszValidInput);
}
printf("\r\n\r\n");
for (int i = 0; i < N; i++)
{
for (int j = 0; j < M; j++)
{
//if the memory content is not 0xFF (means it's a valid value), then print
if (*(pnMap + i * M + j) != 0xFFFFFFFF)
{
printf("%d", *(pnMap + i * M + j));
}
}
printf("\r\n");
}
free(Line);
free(pszValidInput);
free(pnMap);
return 0;
}
void buildMap(int *map, int i, char * line)
{
for (int j = 0; j < strlen(line); j++)
{
(int) *((int *)map + j) = line[j] - '0';
}
}
我使用的是“int”而不是“long long”,但如果你坚持继续使用“long long”,那么应该没有任何问题。如果继续使用“long long”,则打印出数组值时的条件应改为:
if (*(pnMap + i * M + j) != 0xFFFFFFFF)
到
if (*(pnMap + i * M + j) != 0xFFFFFFFFFFFFFFFF)
还有一些关于用户输入验证的其他修改,我在代码中写了一些附加注释。