简体   繁体   English

如何在不使用循环的情况下快速打印由指针组成的2个字符的二维数组?

[英]How can I quickly printf 2 dimensional array of chars made of pointers to pointers without using a loop?

I'm making ASCII game and I need performance, so decided to go with printf(). 我正在制作ASCII游戏,并且需要性能,因此决定使用printf()。 But there is a problem, I designed my char array as multidimensional char ** array, and printing it outputs garbage of memory instead of data. 但是有一个问题,我将我的char数组设计为多维char **数组,并打印它会输出内存垃圾,而不是数据。 I know it's possible to print it with a for loop but the performance rapidly drops that way. 我知道可以使用for循环打印它,但是性能会迅速下降。 I need to printf it like a static array[][]. 我需要像静态array [] []那样打印它。 Is there a way? 有办法吗?

I did some example of working and notWorking array. 我做了一些工作和不工作数组的例子。 I only need printf() to work with nonWorking array. 我只需要printf()来处理nonWorking数组。

edit: using Visual Studio 2015 on Win 10, and yeah, I tested performance and cout is much slower than printf (but I don't really know why is this happening) 编辑:在Win 10上使用Visual Studio 2015,是的,我测试了性能,cout比printf慢得多(但我真的不知道为什么会这样)

#include <iostream>
#include <cstdio>

int main()
{
    const int X_SIZE = 40;
    const int Y_SIZE = 20;

    char works[Y_SIZE][X_SIZE];
    char ** notWorking;

    notWorking = new char*[Y_SIZE];
    for (int i = 0; i < Y_SIZE; i++) {
        notWorking[i] = new char[X_SIZE];
    }

    for (int i = 0; i < Y_SIZE; i++) {
        for (int j = 0; j < X_SIZE; j++) {
            works[i][j] = '#';
            notWorking[i][j] = '#';
        }
        works[i][X_SIZE-1] = '\n';
        notWorking[i][X_SIZE - 1] = '\n';
    }
    works[Y_SIZE-1][X_SIZE-1] = '\0';
    notWorking[Y_SIZE-1][X_SIZE-1] = '\0';

    printf("%s\n\n", works);
    printf("%s\n\n", notWorking);

    system("PAUSE");
}

Note: I think I could make some kind of a buffer or static array for just copying and displaying data, but I wonder if that can be done without it. 注意:我想我可以为复制和显示数据制作某种缓冲区或静态数组,但是我想知道如果没有它是否可以做到。

If you would like to print a 2D structure with printf without a loop, you need to present it to printf as a contiguous one-dimension C string. 如果要使用不带循环的printf打印2D结构,则需要将其作为连续的一维C字符串呈现给printf Since your game needs access to the string as a 2D structure, you could make an array of pointers into this flat structure that would look like this: 由于您的游戏需要以2D结构形式访问字符串,因此您可以在该扁平结构中创建一系列指针,如下所示:

数组和缓冲区

Array of pointers partitions the buffer for use as a 2D structure, while the buffer itself can be printed by printf because it is a contiguous C string. 指针数组将缓冲区划分为2D结构,而缓冲区本身可以由printf打印,因为它是连续的C字符串。

Here is the same structure in code: 这是代码中的相同结构:

// X_SIZE+1 is for '\n's; overall +1 is for '\0'
char buffer[Y_SIZE*(X_SIZE+1)+1];
char *array[Y_SIZE];
// Setup the buffer and the array
for (int r = 0 ; r != Y_SIZE ; r++) {
    array[r] = &buffer[r*(X_SIZE+1)];
    for (int c = 0 ; c != X_SIZE ; c++) {
        array[r][c] = '#';
    }
    array[r][X_SIZE] = '\n';
}
buffer[Y_SIZE*(X_SIZE+1)] = '\0';
printf("%s\n", buffer);

Demo. 演示

Some things you can do to increase performance: 您可以采取一些措施来提高性能:

  • There is absolutely no reason to have an array of pointers, each pointing at an array. 绝对没有理由要有一个指针数组,每个指针都指向一个数组。 This will cause heap fragmentation as your data will end up all over the heap. 这将导致堆碎片,因为您的数据最终将遍及整个堆。 Allocating memory in adjacent cells have many benefits in terms of speed, for example it might improve the use of data cache. 在速度方面,在相邻单元中分配内存有很多好处,例如,它可以改善数据缓存的使用。

    Instead, allocate a true 2D array: 而是分配一个真正的2D数组:

     char (*array2D) [Y] = new char [X][Y]; 
  • printf as well as cout are both incredibly slow, as they come with tons of overhead and extra features which you don't need. printfcout都非常慢,因为它们带有大量的开销和您不需要的额外功能。 Since they are just advanced wrappers around the system-specific console functions, you should consider using the system-specific functions directly. 由于它们只是围绕系统特定的控制台功能的高级包装,因此您应考虑直接使用系统特定的功能。 For example, the Windows console API . 例如, Windows控制台API It will however turn your program non-portable. 但是,这将使您的程序不可移植。

    If that's not an option, you could try to use puts instead of printf , since it has far less overhead. 如果这不是一个选择,那么您可以尝试使用puts而不是printf ,因为它的开销要少得多。

  • Main performance issue with printf/cout is that they write to the end of the "standard output stream", meaning you can't write where you like, but always at the bottom of the screen. printf / cout的主要性能问题是它们写入“标准输出流”的末尾,这意味着您无法在所需的位置写入,但始终在屏幕底部。 Forcing you to constantly redraw the whole thing every time you changed something, which will be slow and possibly cause flicker issues. 强迫您每次更改某些内容时都不断重绘整个对象,这会很慢,并可能导致闪烁问题。

    Old DOS/Turbo C programs solved this with a non-standard function called gotoxy which allowed you to move the "cursor" and print where you liked. 旧的DOS / Turbo C程序通过一个称为gotoxy的非标准功能解决了该问题,该功能使您可以移动“光标”并在所需的位置打印。 In modern programming, you can do this with the console API functions. 在现代编程中,您可以使用控制台API函数来执行此操作。 Example for Windows . Windows的示例

  • You could/should separate graphics from the rest of the program. 您可以/应该将图形与程序的其余部分分开。 If you have one thread handing graphics only and the main thread handling algorithms, the graphic updates will work smoother, without having to wait for whatever else the program is doing. 如果只有一个线程处理图形,并且只有主线程处理算法,则图形更新将更加流畅,而不必等待程序正在执行的其他任何操作。 It makes the program far more advanced though, as you have to consider thread safety issues. 但是,由于您必须考虑线程安全性问题,因此它使程序更加高级。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM