我一直在尝试将程序从Java转换为C,它是手表的模拟器并显示我使用Ascii艺术的时间。我已将所有数字(0-9)存储在2D字符数组(fx.9)中:
char nine[7][5] = {
{ '0', '0', '0', '0' },
{ '0', ' ', ' ', '0' },
{ '0', ' ', ' ', '0' },
{ '0', '0', '0', '0' },
{ ' ', ' ', ' ', '0' },
{ ' ', ' ', ' ', '0' },
{ ' ', ' ', ' ', '0' }
};
我现在有一个函数,它的作用是转换存储在int数组中的时间(fx.22:04:59,将在数组中存储为220459)。该函数应该将相应的Ascii art返回给每个数字,这样我最终可以调用打印时间(以ascii形式)的函数,该函数需要6个char [] []参数。
简而言之,我需要知道用这个函数调用哪个参数:
void printScreen(char hourFirstDigit[7][5], char hourSecondDigit[7][5], char minuteFirstDigit[7][5], char minuteSecondDigit[7][5], char secFirstDigit[7][5], char secSecondDigit[7][5])
在java中我的解决方案只是创建一个返回char [] []数组的函数,然后是10个案例(0-9)的switch语句,(这里是前几行):
char timeToAsciiArt[][](int digitNumber, int small) {
switch (timeRightNow[digitNumber]) {
case 0:
return zero;
}
可能的解决方案: 我已经读过那里至少有两个可能解决问题的方法(一般来说),1。用指针替换数组。 2.用结构包裹。
我的想法: 1.我真的不确定如何返回指向数组的指针(有人可以用案例0来解释如何执行此操作:作为示例?:)
答案 0 :(得分:2)
我建议如下。方法。
定义一个函数,该函数将包含具有静态存储持续时间的图像数组。
例如
char ( * )[7][5] get_image( size_t i )
{
static char images[10][7][5] =
{
//...
{
{ '0', '0', '0', '0' },
{ '0', ' ', ' ', '0' },
{ '0', ' ', ' ', '0' },
{ '0', '0', '0', '0' },
{ ' ', ' ', ' ', '0' },
{ ' ', ' ', ' ', '0' },
{ ' ', ' ', ' ', '0' }
}
};
const size_t N = sizeof( images ) / sizeof( *images );
return i < N ? images[i] : NULL;
}
或者如果函数返回类型char ( * )[5]
例如
char ( * )[5] get_image( size_t i )
{
static char images[10][7][5] =
{
//...
{
{ '0', '0', '0', '0' },
{ '0', ' ', ' ', '0' },
{ '0', ' ', ' ', '0' },
{ '0', '0', '0', '0' },
{ ' ', ' ', ' ', '0' },
{ ' ', ' ', ' ', '0' },
{ ' ', ' ', ' ', '0' }
}
};
const size_t N = sizeof( images ) / sizeof( *images );
return i < N ? images[i][0] : NULL;
}
然后编写一个函数,它将在结构中返回一个包含相应数字的6个元素的数组。这些元素将作为调用函数get_image
的参数。
这就够了。
答案 1 :(得分:2)
据我了解,您希望:
将ASCII艺术包装到结构中可能是明智之举,因为您可以存储更多关于它的数据。也许在将来你会想要一个更薄的1
数字;您需要存储有关每种ASCII艺术品大小的数据:
struct ascii_digit {
unsigned int width;
unsigned int height;
char[MAX_HEIGHT][MAX_WIDTH] art; //Here you could instead use a pointer
//instead of storing directly
}
当然,如果您绝对不打算使用固定大小以外的其他内容,那么阵列就可以了。
在C中传递数组时,通常不直接传递数组:通常使用指向它的指针。所以你的函数的正确原型不会是
char time_to_ascii_art[][](int digit_number, int small);
但是,如果你使用结构
struct ascii_digit* time_to_ascii_art(int digit_number, int small);
请注意,我们返回一个指向结构的指针。尽管绝对可以直接传递结构,但它可能不被认为是一种好的做法,因为它会根据结构的大小产生一些开销。
或者您可以使用指向char
的
char* time_to_ascii_art(int digit_number, int small);
请注意,如果您有一个指向二维数组的char*
指针,则在尝试访问其内容时,您必须自己进行数学运算。例如,访问y
行的x
成员:array[width * x + y]
。为了避免这样做,您可以使用指向数组的指针:
char (*time_to_ascii_art)(int digit_number, int small)[ASCII_ART_WIDTH];
在这个函数中,您可以像使用Java一样使用switch … case
语句(使用结构的示例):
// Let's say that your structures are declared in the global scope as ascii_zero, ascii_one…
struct ascii_digit* time_to_ascii_art(int digit_number, int small)
{
switch(digit_number) {
case 0:
return ascii_zero;
case 1:
return ascii_one;
default:
return NULL;
}
}
或者你可以 - 在Java中也可能是一个好主意 - 有一个包含你的ASCII艺术的数组,或指向它们的指针,索引,以便访问n
成员将为你提供ASCII艺术数字n
:
// Let's now say you have an ascii_digits array of structs containing your digits
struct ascii_digit* time_to_ascii_art(int digit_number, int small)
{
return ascii_digits + digit_number; // You should handle bad values.
// ascii_digits being an array, it is implicitly cast to a pointer here.
}
现在将您的ASCII艺术传递给您的显示功能,您可以 - 根据您选择的数据类型 - 使用指向结构的指针:
void print_screen(struct ascii_digit* hour_first_digit, …);
指向char
的指针:
void print_screen(char* hour_first_digit, …);
或指向字符数组的指针:
void print_screen(char (*hour_first_digit)[ASCII_ART_WIDTH], …);
答案 2 :(得分:1)
在C中,数组是指针。当你传递参数时,它总是通过复制,所以当你“发送”一个数组时,你会发送一个指针的副本,而不是数组的副本。
结构按值复制(int
,float
...),并且可以包含静态数组:
typedef struct {
char tab[7][5];
}Digit;
因此,您可以创建变量:Digit zero, one, two…
并将值设置到其中:zero.tab[0][0] = ' ';
。你可以将它传递给函数或返回它,它将被复制。
现在处理指针(在我看来更好,因为你不需要来复制这些数组):数组仍然是一个指针。但是“静态”2D数组有点奇怪(它不是数组数组)。正如EOF在评论中提到的那样,你的数组实际上是(*)[5]。所以它导致一些有点复杂的东西匹配所有类型:
char (*select_digit(int val))[5] {
if (value == 0) return zero;
if (value == 1) return one;
…
}
您的printScreen
功能是一样的。
要存储由此select_digit
函数返回的指针,您必须将其声明为:
char (*tmp)[5];
tmp = select_digit(5);
printScreen(tmp, …);
答案 3 :(得分:1)
您使用数组和指针的想法或多或少会转化为:
char (* timeToAsciiArt(unsigned timeNow[6], unsigned digitNumber) )[5] {
static char asc0[7][5] = { //fill in };
static char asc1[7][5] = { //fill in };
switch (timeNow[digitNumber]) {
case 0:
return asc0;
case 1:
return asc1;
...
}
然后,您可以通过
将返回的作品传递给print_screen
unsigned timeNow[] = {1, 2, 3, 4, 5, 6};
char (*first_digit)[5] = timeToAsciiArt(timeNow, 0);
printScreen(first_digit, ... , );
或直接
printScreen( timeToAsciiArt(timeNow, 0) , ...);
最后,这可以说在struct
中包装将为您提供更易读的代码。