ncurses程序输入1后彩色条带重复显示问题排查
问题描述
开发的ncurses程序在main函数的while循环前会打印一条彩色条带;当用户输入1后,程序通过adjustedConstant()计算4种可见范围内的波长,对应颜色数组位置打印随机字符,其余位置输出空格。但实际运行时(编译参数-lncursesw,运行环境xfce4-terminal),输入1后条带会额外重复3次,共显示4条,而预期仅显示1条。输入1后输出的波长信息如下:
1n = 2, 2n = 3, Wavelength: 6.564696e-07 meters
1n = 2, 2n = 4, Wavelength: 4.862738e-07 meters
1n=2, 2n=5, Wavelength: 4.341730e-07 meters
1n=2, 2n=6, Wavelength: 4.102935e-07 meters
问题原因
核心问题出在内层波长计算循环的逻辑:当前代码每计算出一个可见波长,就完整打印一遍整条彩色条带。因为有4个可见波长,所以会触发4次条带打印,最终屏幕上出现4条重复内容。
修复方案
修改内层循环逻辑,先收集所有可见波长对应的索引,再一次性绘制条带,仅输出1条包含所有目标随机字符的彩色条带:
#include <stdio.h> #include <stdlib.h> #include <curses.h> #include <locale.h> #include <math.h> typedef struct { int r; int g; int b; } RGB; RGB newRGB(int r, int g, int b) { RGB color; color.r = r; color.g = g; color.b = b; return color; } void calculateColor(RGB *colors, int totalColors, int currentIndex, float saturation, float luminosity); double adjustedConstant() { return 1.0973731568508E7 / (1 + 9.10938356E-31 / 1.67262192E-27); } int main() { setlocale(LC_ALL, ""); int totalColors = 60; RGB colors[totalColors]; float saturation = 1.0; float luminosity = 0.3; initscr(); start_color(); int end = totalColors - 18; int start = end - 42; for (int i = end; i >= start; i--) { calculateColor(&colors[i], totalColors, i, saturation, luminosity); // 转换RGB颜色为curses默认模型 int r = colors[i].r * 1000 / 255; int g = colors[i].g * 1000 / 255; int b = colors[i].b * 1000 / 255; // 在curses中设置颜色 init_color(i + 16, r, g, b); init_pair(i + 16, COLOR_BLACK, i + 16); // 打印初始彩色条带 attron(COLOR_PAIR(i + 16)); printw(" "); attroff(COLOR_PAIR(i + 16)); } // 用于绘制的字符集合 int characters[] = { 9474, 9475, 10072, 10073, 12321 }; int numCharacters = sizeof(characters) / sizeof(characters[0]); while (1) { int number; printw("\n\nEnter 1 or -1 to exit: "); scanw("%d", &number); if (number == -1) { break; } // 收集所有可见波长对应的颜色索引 int visibleIndices[10]; // 数组大小足够容纳所有可见波长 int indexCount = 0; int n1 = 1, n2 = 2; double lambda_a = 0; while (1) { lambda_a = 1.0 / (adjustedConstant() * ((1.0 / (n1 * n1)) - (1.0 / (n2 * n2)))); if (lambda_a >= 400E-9 && lambda_a <= 700E-9) { int index = (700 - lambda_a * 1e9) * (totalColors - 10.5) / (750 - 380); visibleIndices[indexCount++] = index; } if (lambda_a > 700E-9) { break; } n2++; if (n2 <= 6) { continue; } n1++; n2 = n1 + 1; } // 定位到初始条带下方(可选,避免覆盖原有内容) move(LINES - 3, 0); // 一次性绘制包含所有目标字符的条带 for (int i = end; i >= start; i--) { attron(COLOR_PAIR(i + 16)); // 检查当前索引是否属于可见波长位置 int isVisible = 0; for (int j = 0; j < indexCount; j++) { if (i == visibleIndices[j]) { isVisible = 1; break; } } if (isVisible) { int randomCharacter = characters[rand() % numCharacters]; wprintw(stdscr, "%lc ", randomCharacter); // 补空格对齐初始条带的双空格格式 } else { printw(" "); } attroff(COLOR_PAIR(i + 16)); } refresh(); } getch(); endwin(); return 0; } void calculateColor(RGB *colors, int totalColors, int currentIndex, float saturation, float luminosity) { float hue = currentIndex * (360.0 / totalColors); float chroma = (1 - fabs(2 * luminosity - 1)) * saturation; float x = chroma * (1 - fabs(fmod(hue / 60, 2) - 1)); float m = luminosity - chroma / 2; float r, g, b; if (hue >= 0 && hue < 60) { r = chroma; g = x; b = 0; } else if (hue >= 60 && hue < 120) { r = x; g = chroma; b = 0; } else if (hue >= 120 && hue < 180) { r = 0; g = chroma; b = x; } else if (hue >= 180 && hue < 240) { r = 0; g = x; b = chroma; } else if (hue >= 240 && hue < 300) { r = x; g = 0; b = chroma; } else { r = chroma; g = 0; b = x; } colors->r = (r + m) * 255; colors->g = (g + m) * 255; colors->b = (b + m) * 255; }
关键修改点
- 新增索引收集逻辑:先遍历所有波长计算,将可见波长对应的颜色索引存入数组,不再每计算一个波长就打印一次条带。
- 统一绘制条带:遍历颜色条带时,检查当前索引是否在可见列表中,是则打印随机字符(补空格对齐初始格式),否则打印空格,仅执行一次完整条带绘制。
- 可选位置调整:用
move()函数定位到屏幕下方,避免覆盖初始条带内容。
内容的提问来源于stack exchange,提问作者Exponecial
相关产品推荐
相关产品推荐

