很久很久以前我和C
玩了很多但忘记了一切。现在我正在努力解决简单的任务并失败。
我想编写一个带2dim数组或char*
的函数并打印出来。但我的代码是错误的,我不明白为什么。据我所知,products
是指向2dim数组的指针,所以将它增加到i * sizeof(char**)
我得到指向子数组的指针,并且增加该子数组指针我得到指向char块的指针。但似乎我的代码寻找不同的内存块。
关于products
数组 - 我知道它有N行和2列。
#include <stdio.h>
#include <string.h>
void print(char*** products, size_t rows, size_t cols) {
size_t i;
for(i = 0; i < rows; i++) {
printf("Col1: '%s. Col2: %s'\n",
(products + i * sizeof(char**)),
(products + i * sizeof(char**) + sizeof(char*))
);
}
}
int main(void) {
const char* a[][3] = {{"abc", "1"}, {"def", "2"}, {"ghi", "3"}};
print((char***)a, 3, 2);
return 0;
}
答案 0 :(得分:3)
此声明中定义的数组
const char* a[][3] = {{"abc", "1"}, {"def", "2"}, {"ghi", "3"}};
的类型为const char *[3][3]
。
考虑到数组有三个“列”,在数组声明中明确指定了3列。
const char* a[][3] =....
^^^
最后一列中的元素由NULL
初始化。
当在表达式中使用数组时,例如作为参数,它被显式转换为指向其第一个元素的指针。
即如果您使用上面显示的数组作为参数,那么它将转换为类型
const char * ( * )[3]
它与char ***
因此该函数应该声明为
void print( const char * ( *products )[3], size_t rows );
或喜欢
void print( const char * products[][3], size_t rows );
并且应该像
一样调用该函数print( a, 3 );
您可以再指定一个参数来设置您想要输出的列数
void print( const char * ( *products )[3], size_t rows, size_t cols );
在这种情况下,可以像
一样调用该函数print( a, 3, 2 );
然而,阵列本身在任何情况下都有3列。:)
或者编译器是否支持像
这样的可变长度数组void print( size_t rows, size_t cols, const char * ( *products )[cols] );
或为了便于阅读
void print( size_t rows, size_t cols, const char * products[rows][cols] );
可以像
一样调用print( 3, 3, a );
这是一个演示程序,它显示了函数声明的两种方法
#include <stdio.h>
#include <string.h>
#define N 3
void print1( const char *product[][N], size_t rows )
{
for ( size_t i = 0; i < rows; i++ )
{
for ( const char **p = product[i]; *p; ++p )
{
printf( "%s ", *p );
}
printf( "\n" );
}
}
void print2( size_t rows, size_t cols, const char *product[rows][cols] )
{
for ( size_t i = 0; i < rows; i++ )
{
for ( const char **p = product[i]; *p; ++p )
{
printf( "%s ", *p );
}
printf( "\n" );
}
}
int main( void )
{
const char * a[][N] =
{
{ "abc", "1" },
{ "def", "2" },
{ "ghi", "3" }
};
print1( a, N );
printf( "\n" );
size_t n = N;
const char * b[n][n];
memcpy( b, a, sizeof( a ) );
print2( n, n, b );
printf( "\n" );
}
它的输出是
abc 1
def 2
ghi 3
abc 1
def 2
ghi 3
考虑到编译器支持的可变长度数组可能无法初始化,然后定义它们。
答案 1 :(得分:1)
const char* a[][3] = {{"abc", "1"}, {"def", "2"}, {"ghi", "3"}};
在这种情况下,您实际上可以写:
const char* a[][2] = {{"abc", "1"}, {"def", "2"}, {"ghi", "3"}};
但是如果你真的想要一个3列数组,你应该告诉print有3列,而不是2.但是你的打印只能打印两个第一列...
然后,T
的任何N维数组都可以被视为T
的简单一维数组。您只需进行一些地址计算即可访问所需的元素。一旦你有一个指向数组的第一项的指针,这是可能的。以下是工作版本:
#include <stdio.h>
#include <string.h>
typedef const char * T;
void print(T *products, size_t rows, size_t cols) {
size_t i;
for (i = 0; i < rows; i++) {
// Each row has cols items so here is the current row (i-th row):
T *row = products + i * cols;
printf("{%s, %s}\n", row[0], row[1]);
}
}
int main(void) {
T a[][3] = { { "abc", "1" }, { "def", "2" }, { "ghi", "3" } };
// Tell print that there are 3 cols, not 2
print(&a[0][0], 3, 3);
return 0;
}
答案 2 :(得分:1)
你混淆了你认为的列和行。解决这个问题,然后摆脱三星级的废话,让函数接受可变数量的列,你最终得到这个:
#include <stdio.h>
void print(size_t rows, size_t cols, const char* products[rows][cols])
{
for(size_t r=0; r<rows; r++)
{
for(size_t c=0; c<cols; c++)
{
printf("Col%zu: %s. ", c, products[r][c]);
}
printf("\n");
}
}
int main (void)
{
const char* a[3][2] = {{"abc", "1"}, {"def", "2"}, {"ghi", "3"}};
print(3, 2, a);
return 0;
}
就是这样,不需要再复杂化了。
答案 3 :(得分:0)
也许,这就是你想要的,这更自然!
#include <stdio.h>
#include <string.h>
void print(void *_products, size_t rows, size_t cols) {
const char* (*products)[cols] = _products;
size_t i;
for (i = 0; i < rows; i++) {
printf("Col1: %s. Col2: %s\n", products[i][0], products[i][1]);
}
}
int main(void) {
const char* a[][2] = {{"abc", "1"}, {"def", "2"}, {"ghi", "3"}};
print(a, 3, 2);
return 0;
}