我有这个功能,目的是迭代2D数组并访问2D数组中的单个字符。但char** buffer
正在成为2D数组中字符串的一个点,而不是单个字符。
这是我的功能:
bool screen_graph_interator(screen_graph_t* local, char** buffer, uint32_t* iteration, uint32_t start_x, uint32_t start_y, uint32_t width, uint32_t height)
{
// local variables
int x, y;
// TODO: Check for valide start_x, start_y, width, height inputs againsts local screen_graph
// get index
x = start_x + *iteration % width;
y = start_y + *iteration / width;
// if we're beyond domain and range we're done iterating
if(*iteration > (width * height)-1) {
*buffer = NULL;
return false;
}
// get char ptr
*buffer = &(local->field[x][y]);
(*iteration)++;
return true;
}
这一行是我认为包含我的错误*buffer = &(local->field[x][y]);
我在调试器中看到的是:new_char = 0x804a52c " XXXXXX "
new_char是char*
我传递给char** buffer
似乎new_char的值是一个字符串我是对的吗?
当我拨打printf("%s\n\r", new_char);
时,它会打印整个字符串。
编辑:
如果你想运行我的代码,那么screen_graph_t
typedef struct screen_graph {
char field[DISPLAY_ROWS][DISPLAY_COLS];
bool expired;
} screen_graph_t;
编辑:
以下是我调用screen_graph_interator的方法:
bool screen_graph_changes(screen_graph_t* old_graph, screen_graph_t* new_graph) {
// local variables
char* old_char = NULL;
char* new_char = NULL;
uint32_t iteration = 0; // the screen_graph iteration index
uint32_t vt_string_index = 0; // the position in the VT100 string, to be sent to putty session
uint32_t skip_count = 0; // the char count not changed
while(screen_graph_interator(old_graph, &old_char, &iteration, 0, 0, DISPLAY_COLS, DISPLAY_ROWS)) {
iteration--;
screen_graph_interator(new_graph, &new_char, &iteration, 0, 0, DISPLAY_COLS, DISPLAY_ROWS);
// check for character differences
if( *old_char != *new_char
&& *new_char != '\0') {
// determine if we need a VT100 jump
if(skip_count > 0) {
...
答案 0 :(得分:1)
获取上面的代码片段并将它们转换为问题中应该提供的MCVE(Minimal, Complete, Verifiable Example)并添加一些基本断言,最终可以得到如下代码:
#include <assert.h>
#include <stdbool.h>
#include <inttypes.h>
#include <stdio.h>
enum { DISPLAY_ROWS = 24, DISPLAY_COLS = 50 };
typedef struct screen_graph
{
char field[DISPLAY_ROWS][DISPLAY_COLS];
bool expired;
} screen_graph_t;
static bool screen_graph_interator(screen_graph_t *local, char **buffer,
uint32_t *iteration, uint32_t start_x, uint32_t start_y,
uint32_t width, uint32_t height)
{
int x = start_x + *iteration % width;
int y = start_y + *iteration / width;
if (*iteration > (width * height) - 1)
{
*buffer = NULL;
return false;
}
*buffer = &(local->field[x][y]);
assert(*buffer >= &local->field[0][0] &&
*buffer <= &local->field[DISPLAY_ROWS-1][DISPLAY_COLS-1]);
(*iteration)++;
return true;
}
static bool screen_graph_changes(screen_graph_t *old_graph, screen_graph_t *new_graph)
{
char *old_char = NULL;
char *new_char = NULL;
uint32_t iteration = 0;
while (screen_graph_interator(old_graph, &old_char, &iteration, 0, 0, DISPLAY_COLS, DISPLAY_ROWS))
{
iteration--;
screen_graph_interator(new_graph, &new_char, &iteration, 0, 0, DISPLAY_COLS, DISPLAY_ROWS);
assert(old_char >= &old_graph->field[0][0] &&
old_char <= &old_graph->field[DISPLAY_ROWS-1][DISPLAY_COLS-1]);
assert(new_char >= &new_graph->field[0][0] &&
new_char <= &new_graph->field[DISPLAY_ROWS-1][DISPLAY_COLS-1]);
if (*old_char != *new_char && *new_char != '\0')
{
printf("Different: %" PRIu32 "\n", iteration);
return true;
}
}
return false;
}
int main(void)
{
screen_graph_t old_graph = { 0 };
screen_graph_t new_graph = { 0 };
old_graph.field[DISPLAY_ROWS-1][DISPLAY_COLS-1] = 'O';
new_graph.field[DISPLAY_ROWS-1][DISPLAY_COLS-1] = 'N';
screen_graph_changes(&old_graph, &new_graph);
return 0;
}
请注意,严格来说,如果地址超出数组的范围,则断言中的地址比较是不可靠的(
运行时,它会因断言失败而崩溃。来源位于ob17.c
:
Assertion failed: (*buffer >= &local->field[0][0] && *buffer <= &local->field[DISPLAY_ROWS-1][DISPLAY_COLS-1]), function screen_graph_interator, file ob17.c, line 30.
Abort trap: 6
如果将DISPLAY_ROWS设置为等于DISPLAY_COLS,则不会触发断言。他们两人都在24岁时产生:
Different: 576
如果在调用screen_graph_iterator()
时交换参数DISPLAY_ROWS和DISPLAY_COLS,则不会触发断言。使用24和50值,它产生:
Different: 1200
基本问题是你正在访问数组越界,因为你在x
函数中反转了y
和screen_graph_iterator()
的表达式。因此,该问题的另一个解决方案使用:
#include <assert.h>
#include <stdbool.h>
#include <inttypes.h>
#include <stdio.h>
enum { DISPLAY_ROWS = 24, DISPLAY_COLS = 50 };
//enum { DISPLAY_ROWS = 24, DISPLAY_COLS = 24 };
typedef struct screen_graph
{
char field[DISPLAY_ROWS][DISPLAY_COLS];
bool expired;
} screen_graph_t;
static bool screen_graph_interator(screen_graph_t *local, char **buffer,
uint32_t *iteration, uint32_t start_x, uint32_t start_y,
uint32_t width, uint32_t height)
{
int y = start_x + *iteration % width;
int x = start_y + *iteration / width;
//int x = start_x + *iteration % width;
//int y = start_y + *iteration / width;
if (*iteration > (width * height) - 1)
{
*buffer = NULL;
return false;
}
*buffer = &(local->field[x][y]);
assert(*buffer >= &local->field[0][0] &&
*buffer <= &local->field[DISPLAY_ROWS-1][DISPLAY_COLS-1]);
(*iteration)++;
return true;
}
static bool screen_graph_changes(screen_graph_t *old_graph, screen_graph_t *new_graph)
{
char *old_char = NULL;
char *new_char = NULL;
uint32_t iteration = 0;
while (screen_graph_interator(old_graph, &old_char, &iteration, 0, 0, DISPLAY_COLS, DISPLAY_ROWS))
//while (screen_graph_interator(old_graph, &old_char, &iteration, 0, 0, DISPLAY_ROWS, DISPLAY_COLS))
{
iteration--;
screen_graph_interator(new_graph, &new_char, &iteration, 0, 0, DISPLAY_COLS, DISPLAY_ROWS);
//screen_graph_interator(new_graph, &new_char, &iteration, 0, 0, DISPLAY_ROWS, DISPLAY_COLS);
assert(old_char >= &old_graph->field[0][0] &&
old_char <= &old_graph->field[DISPLAY_ROWS-1][DISPLAY_COLS-1]);
assert(new_char >= &new_graph->field[0][0] &&
new_char <= &new_graph->field[DISPLAY_ROWS-1][DISPLAY_COLS-1]);
if (*old_char != *new_char && *new_char != '\0')
{
printf("Different: %" PRIu32 "\n", iteration);
return true;
}
}
return false;
}
int main(void)
{
screen_graph_t old_graph = { 0 };
screen_graph_t new_graph = { 0 };
old_graph.field[DISPLAY_ROWS-1][DISPLAY_COLS-1] = 'O';
new_graph.field[DISPLAY_ROWS-1][DISPLAY_COLS-1] = 'N';
screen_graph_changes(&old_graph, &new_graph);
return 0;
}
这不会产生断言失败和Different: 1200
输出。
(对于10k用户,问题的前一版本为Can't pass local struct reference to another function。它遇到了同样的问题。) 功能