用于读取矩阵 C++ 的宏
Posted
技术标签:
【中文标题】用于读取矩阵 C++ 的宏【英文标题】:Macro for reading matrix C++ 【发布时间】:2016-06-29 22:04:39 【问题描述】:我正在尝试定义宏以在 C++ 中读取和打印矩阵,但我尝试了一些不同的方法,但它不起作用:
#define rm(A, m, n, type)
for(int i = 0; i < m; i++)
for(int j = 0; j < n; j++)
scanf("%##type##", &A[i][j]);
A 是矩阵(int 或 char)
我想写 d 或 c 来读取 int 或 char,但这段代码不起作用,我什至不知道为什么,我只是尝试使用 concat ## 符号来创建 scanf 接收的字符串论据,但它有错误。
我的问题是:
1 - 为什么错了?
2 - 我怎样才能使这个宏正常工作? (如有必要,解决方案可能包含 1 或 2 个宏声明,但很短,否则我不会问,我可以为 int 创建一个宏,为 char 创建其他宏。
PS:这个宏写了一行,上面的算法只是为了展示它的作用。
谢谢
【问题讨论】:
宏是邪恶的。使其成为内联函数。例如,宏允许您将“hello”作为一个参数传递,将“Frog”作为类型传递。 顺便说一句,使用花括号
和
不会影响运行时并且对编译的影响可以忽略不计。使用它们。这是一种减少缺陷的方法。
我认为问题在于替换字符文字。您可能必须传递整个 scanf
格式字符串。
不要费心阅读第二个矩阵。这个系列在第一个之后真的走下坡路了。
【参考方案1】:
如果您真的必须为此创建一个宏 - 正如其他人所指出的那样,这是一个非常糟糕的想法,而不是正确的方法 - 您遇到的问题是该宏由预处理器解释,它将换行符视为宏替换的结束。要解决此问题,您需要在行尾引入一些转义序列:
#define rm(A, m, n, type) \
for(int i = 0; i < m; i++) \
for(int j = 0; j < n; j++) \
scanf("%" #type, &A[i][j]);
请注意,我已经从字符串内部排除了您对令牌粘贴运算符的使用,因为预处理器不会为您填写字符串文字,而是选择使用字符串化运算符 #
来将类型转换为字符串文字。由于编译器会自动将相邻的字符串文字连接在一起,因此无需粘贴任何内容。我应该重申这是一个非常糟糕的主意,因为它会损害代码的可读性,并且不能提供常规 C++ 函数无法提供的任何功能。
不过,您已将此问题标记为 C++,因此我应该指出,scanf
可能会出现各种类型安全问题,因此使用 iostream
库几乎可以肯定更安全,该库用于它的所有错误都会在编译时捕获大量可能的错误。
不过,从根本上说,您不应该为此使用宏。只需编写一个常规的旧函数。这是执行此操作的一种方法,它具有自动推断数组大小的额外好处:
template <typename T, size_t m, size_t n>
void readArray(T (&array)[m][n], std::istream& source = std::cin)
for (size_t i = 0; i < m; i++)
for (size_t j = 0; j < n; j++)
source >> array[i][j];
现在,你可以这样说:
double arr[137][42];
readArray(arr);
从cin
中读取double
s 的数组,或者
int arr[5][5];
ifstream input("my-file.txt");
readArray(arr, input);
从外部文件中读取int
s 的数组。这是类型安全的,如果您在未定义数组大小或无法读取类型的情况下尝试读取,则会引发编译器错误。这可以防止各种可能的问题。将此与您的宏进行比较,我可以在其中执行以下操作:
int arr[5][5];
rm(arr, 6, 6, f);
糟糕 - 我只是使用了错误的数组大小和错误的 scanf
说明符。任何时候您都可以将工作卸载到编译器,从而使您不必在很多地方进行代码更改,这是值得考虑的!
【讨论】:
以上是关于用于读取矩阵 C++ 的宏的主要内容,如果未能解决你的问题,请参考以下文章