c - 如何引用二维数组中的单个字符?

标签 c arrays string

我有这个函数,目的是迭代二维数组并访问二维数组中的单个字符。但是 char** buffer 正在变成指向二维数组中的字符串的点,而不是单个字符。

这是我的功能:

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** bufferchar*

似乎 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) {

    ...

最佳答案

将上面的代码片段转换成问题中应该提供的 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

基本问题是您正在越界访问数组,因为您在 screen_graph_iterator() 中颠倒了 xy 的表达式 功能。因此,该问题的另一种解决方案是:

#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。它遇到了同样的问题。)

关于c - 如何引用二维数组中的单个字符?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40990884/

相关文章:

c - 如何检查字符数组c中的重复项

c++ - 什么所有的局部变量都转到数据/BSS 段?

C++ 嵌套 for 循环不正确的输出

java - 在java中查找和替换字符串模式

java - 如何用Java进行二进制算术运算?

C++:如何读取 **argv 值并复制到字符串中

c - 如何将两个 C 代码合并为一个?

c - 通过一次删除一个字符来均衡字符串中的字符数

javascript - 如何计算数组中项目的总和?

c# - 当您将对象数组转换为字符串数组时,它叫什么?