【问题标题】:Problem in general with 'char*' type - C++'char*' 类型的一般问题 - C++
【发布时间】:2020-07-25 18:15:25
【问题描述】:

我最近创建了一个表处理类,它几乎由用于输出格式的函数组成,这些函数返回一个char* 变量。我创建了一个演示程序来检查其功能并解决任何类型的问题。现在我陷入了一个问题。这是程序输出:

┌───────┬───────┬───────┐ <-- this series of chars is the top part of the table
│TYPE   │ADDRESS│VALUE  │
├───────┼───────┼───────┤
│N/A    │N/A    │N/A    │
├───────┼───────┼───────┤
│N/A    │N/A    │N/A    │
├───────┼───────┼───────┤
│N/A    │N/A    │N/A    │
└───────┴───────┴───────┘

┌──────────────────────────────────────────────────
──────────────────────────────────────────────────────────── <-- top part gets veeeeeeery long!
│TYPE   │ADDRESS│VALUE  │
├───────┼───────┼───────┤
│N/A    │N/A    │N/A    │
├───────┼───────┼───────┤
│N/A    │N/A    │N/A    │
├───────┼───────┼───────┤
│N/A    │N/A    │A      │<-- in this cell is contained a char* variable value. i think this is the
└───────┴───────┴───────┘ problem

我尝试重新设计顶部函数的算法,但表格必须适应其最大尺寸,因此我无法为每个表格显示相同的顶部。 这是我使用的表头和演示程序:

/* TABLE HEADER */

#ifdef __cplusplus
#define NUL '\0'
#else
#define NUL "\0"
#endif

#include <iostream>
#include <string>
#include <vector>
#include <stdlib.h>

class basic_table
{
private:
    std::vector<std::string> cont_m; //Table content
    int cols_m, rows_m;
    
    int getRecord() //Get the longest string
    {
        int record;
        for (int P = 0, c = 0; P < cont_m.size(); P++)
        {
            while (cont_m[P][c] != NUL) c++;
            record = (record > c ? record : c);
            c = 0;
        }
        return record;
    }
    
    int getLength(int pos) //Localize array position and return string length
    {
        int c = 0;
        while (cont_m[pos][c] != NUL) c++;
        return c;
    }
    
    char* complete(int pos) //Set all string to the same length
    {
        int size = getRecord() - getLength(pos) + 1;
        char* spaces = new char[size];
        for (int P = 0; P < size; P++)
        {
            spaces[P] = ' ';
        }
        spaces[size - 1] = '\0';
        return spaces;
    }
    
    char* bottom() //Bottom part of table formatting
    {
        int size = getRecord() * cols_m + cols_m + 2;
        char* bottom = new char[size];
        bottom[0] = '\300';
        for (int P = 1; P < size - 1; P++)
        {
            for (int R = 1; R <= getRecord(); R++) 
            {
                bottom[P] = '\304';
                P++;
            }
            bottom[P] = (P >= size - 2 ? '\331' : '\301');
        }
        bottom[size - 1] = NUL;
        return bottom;
    }
    
    char* top() //Top part of table formatting
    {
        int size = getRecord() * cols_m + cols_m + 2;
        char* top = new char[size];
        top[0] = '\332';
        for (int P = 1; P < size - 1; P++)
        {
            for (int R = 1; R <= getRecord(); R++) 
            {
                top[P] = '\304';
                P++;
            }
            top[P] = (P >= size - 2 ? '\277' : '\302');
        }
        top[size - 1] = NUL;
        return top;
    }
    
    char* half() //Half part of table formatting
    {
        int size = getRecord() * cols_m + cols_m + 2;
        char* half = new char[size];
        half[0] = '\303';
        for (int P = 1; P < size - 1; P++)
        {
            for (int R = 1; R <= getRecord(); R++) 
            {
                half[P] = '\304';
                P++;
            }
            half[P] = (P >= size - 2 ? '\264' : '\305');
        }
        half[size - 1] = NUL;
        return half;
    }
    
public:
    basic_table(int cols, int rows) : cols_m(cols), rows_m(rows)
    {
        cont_m.resize(cols_m * rows_m); //Set table array size
    }
    
    void fill(int col, int row, std::string text) //Localize array position and set value
    {
        int pos = cols_m * (row - 1) + (col - 1);
        pos = (pos > cols_m * rows_m - 1 ? cols_m * rows_m - 1 : pos < 0 ? 0 : pos); //Protecting against SIGSEGV
        cont_m[pos] = text;
    }
    
    std::string get(int col, int row) //Localize array position and return value
    {
        int pos = cols_m * (row - 1) + (col - 1);
        pos = (pos > cols_m * rows_m - 1 ? cols_m * rows_m - 1 : pos < 0 ? 0 : pos);
        return cont_m[pos];
    }
    
    friend std::ostream& operator<<(std::ostream& stream, basic_table& object) //Display Table
    {
        stream << std::endl;
        stream << object.top() << std::endl;
        if (object.cols_m * object.rows_m == 1)
        {
            stream << '\263' << object.cont_m[0] << '\263' << std::endl << object.bottom() << std::endl;
            return stream;
        }
        for (int C = 0, c = 1; C < object.cols_m * object.rows_m; C++)
        {
            if (c < object.cols_m)
            {
                if (c == 1) stream << '\263';
                stream << object.cont_m[C] << object.complete(C) << '\263';
                c++;
            } else if (C == object.cols_m * object.rows_m - 1) 
            {
                stream << object.cont_m[C] << object.complete(C) << '\263' << std::endl << object.bottom() << std::endl;
                return stream;
            } else {
                c = 1;
                stream << object.cont_m[C] << object.complete(C) << '\263' << std::endl << object.half() << std::endl;
            }
        }
    }
};

typedef basic_table table;

/* DEMO PROGRAM */

//#include "table.h"

int main()
{
    table ptrs(3,4);
    ptrs.fill(1, 1, "TYPE");
    ptrs.fill(2, 1, "ADDRESS");
    ptrs.fill(3, 1, "VALUE");
    ptrs.fill(1, 2, "N/A");
    ptrs.fill(2, 2, "N/A");
    ptrs.fill(3, 2, "N/A");
    ptrs.fill(1, 3, "N/A");
    ptrs.fill(2, 3, "N/A");
    ptrs.fill(3, 3, "N/A");
    ptrs.fill(1, 4, "N/A");
    ptrs.fill(2, 4, "N/A");
    ptrs.fill(3, 4, "N/A");
    std::cout << ptrs;
    char* example = new char;
    *example = 'A';
    ptrs.fill(3, 4, example);
    std::cout << ptrs;
}

【问题讨论】:

  • 您在单个 char 上执行的操作相当于 strlen...?
  • 这个 C 怎么样? C 没有类。
  • 你标记为 C 语言。 C 语言没有classstd::vector。顶部的条件编译毫无价值,因为您的代码不会编译为 C 语言。请根据需要编辑您的语言标签。
  • 查找std::string::length()std::string::size()。您可以使用现有功能消除功能。
  • 我强烈建议拆分文件。将class 定义和方法声明放在头文件中。将函数定义(实现)放入源文件中。照原样,包括头文件在内的任何源文件都必须编译所有这些函数。通过将内容放入源文件中,所有这些函数都将被编译一次。

标签: c++ arrays formatting char


【解决方案1】:

您正在混合使用 C 和 C++,从而打破了基本的编程规则:一致性。

 /* TABLE HEADER */

#ifdef __cplusplus  // useless and dangerous definition !!!!
#define NUL '\0'    // NULL is the correct keyword in C++98, defined in stdlib.h
#else               // std::nullptr_t in c++11 onwards, defined in <cstddefs> 
#define NUL "\0"
#endif

// NEVER, EVER define macros before including library headers !!!!!

#include <iostream>
#include <string>
#include <vector>
#include <stdlib.h>

class basic_table
{
private:
    std::vector<std::string> cont_m; //Table content
                                     // Your table is only 1-D ???
    int cols_m, rows_m;              // useless repetition of table row count.
                                     // let std::vector handle that
                                     // this avoids bugs.

    // correct data definition. 
    std::vector<std::vector<std::string>> cont_m;  // 2D table. dimension:[row, column]

   
    int getRecord() //Get the longest string  // NAME is misleading.
    std::vector<size_t> getMaxCellContentsWidths() // renamed to something more appropriate
                                           // and useable result type           
    {
        int record;
        for (int P = 0, c = 0; P < cont_m.size(); P++) // reserve uppercase names for constants !!!! 
        {
            while (cont_m[P][c] != NUL) c++;
            record = (record > c ? record : c);
            c = 0;
        }
        return record;

        // correct code:

        // returns the maximum length of cell column contents, 
        // does not include padding !!!
        std::vector<size_t> result;
        if (cont_m.empty())
            return result;

        // first table row defines table column count  
        const size_t COL_COUNT = cont_m[0].size();
        result.resize(COL_COUNT);

        for (size_t row = 0; row < cont_m.size(); ++row)
        {
            for (size_t col = 0; col < std::min(COL_COUNT, cont_m[row].size()); ++col)
            {
                // this test is needed if you want to print N/A for empty strings
                size_t w = cont_m[row][col].length();
                if (w == 0) w = 3;
                result[col] = std::max(result[col], w);
            }
        }
        return result;
    }
    
    // your table is 1-D ???
    int getLength(int pos) //Localize array position and return string length

    size_t getItemLength(size_t row, size_t col) 
    {
        // your code, below is 1980's C style programming for embedded applications
        // with nbo access to the C library.  NEVER do this if you can avoid
        // it. 
        int c = 0;
        while (cont_m[pos][c] != NUL) c++;
        return c;

        // correct code:
        if (row >= cont_m.size() || col >= cont_m[row].size())
            return 0;
        return cont_m[row][col].length();
    }
    
    // this bady named funtion is not needed to print a table.
    // and it's leaking memory.
    char* complete(int pos) //Set all string to the same length
    {
        int size = getRecord() - getLength(pos) + 1;
        char* spaces = new char[size];  
        for (int P = 0; P < size; P++)
        {
            spaces[P] = ' ';
        }
        spaces[size - 1] = '\0';
        return spaces;
        // why don't you return a std::string ???
    }

    /* ... */
};

不幸的是,您的代码的其余部分无法修复,因为它假定存储一维表......也就是说,一个只有一列的表。您的错误来自糟糕的原始设计。不要绝望,它会发生的。

重写提示:不要使用原始 char 指针,永远不要调用 new,使用上面定义的函数中的单元格内容宽度,使用 C++ 构造,以及 std 库结构和类。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-23
    • 1970-01-01
    • 1970-01-01
    • 2021-11-16
    • 1970-01-01
    相关资源
    最近更新 更多