一个关于IO的怪问题

张孝祥blog中提到的一个学员提出关于IO的怪问题

一个简单的怪问题

一个学员问了一个关于IO的怪问题,问题是这样的:读取键盘输入的一个字符,然后打印输出这个字符,在打印字符的前面和后面分别加了一个字符串,程序的代码如下:

 

public class Test

{

       public static void main(String [] args) throws Exception

       {

              System.out.print("Input a char:");

              char ch = (char)System.in.read();

              System.out.println("hello" + ch + "AB");

       }

}

 

编译并运行这个程序。

1)输入字符“a”,命令行窗口打印输出的结果如图1所示,与我们预期的一样。

1

 

2)重新运行这个程序,直接按下回车键,在命令行窗口打印输出的结果如图2所示。这时,打印输出的结果是:打印语句中字符后面的字符串“替换”了字符前面的字符串中的部分字符,即打印输出字符串“ABllo”。

2

 

请大家都来想一想,为什么在输入普通字符时,输出的结果是正常的;而直接按下回车键,后面的字符串就“替换”了前面的字符串,并且没有输出回车换行符呢?

 --------------------

上面的问题,是我分析出原因后,为了讲课方便,重新调整的例子,并且写出了错误规律。其实,学员最初的问题非常隐蔽,并没有我上面的案例这么直接,并且找不出错误规律。下面是他当初的程序代码。

 public static void main(String [] args) throws Exception{

  String str="";
  char ch0=0;
  
  System.out.print("intput string and String:");
  do{
   ch0=(char)System.in.read();
   str+=ch0;
  }while(ch0!='#');
  char ch/*='0'*/;
  System.out.print(str);
  ch=(char)System.in.read();
System.out.println("hello" + ch + 'b'); 
 }

----------------------------答案----------------------

读取键盘输入的一个字符时,我们在键盘上按一下回车键,实际上读取到的是两个字符,即“/r”和“/n”。字符“/r”表示回车,即光标回到当前行的行首而不换行;字符“/n”表示换行,即光标移到当前行的下一行行首。
按一下回车键,System.in.read()读取到字符“/r”,当执行到下面的程序代码时:
System.out.println("hello" + ch + "AB");
打印字符串“hello”后,接着打印输出字符“/r”,这时,光标移到字符串“hello”所在当前行的行首,由于没有字符“/n”,不会换到下一行,再继续打印字符串“AB”。这样,字符串“AB”就覆盖了字符串“hello”的前两个字符,所以,我们看到在命令行打印输出的是字符串“ABllo”。 

---------------------进一步评论---------------------- 

yuther 发表于2006-08-10 17:59:00  IP: 58.207.152.*
在Eclipse下,不过没有发现这种问题,我觉得这个是编码方案造成的,Eclipse下运行估记是按Unicode编码来读的两个字节,而MS控制台可能读的是按一个字节来读的,我想讨论一下系统按什么样的编码来读这个语句会更有用一些。
xifo 发表于2006-08-11 08:27:00  IP: 61.191.142.*
这种结果的出现依赖于特定的平台。
Windows平台是以"/r/n"处理回车;
Linux和Unix平台是以"/n/r"处理回车;
至于Eclipse这类跨平台的软件,已经对系统的标准输出设备进行了重定向,测试说明,也是以"/n/r"处理回车。
可以使用标准IO函数和C语言的图像处理库来实现将图片变成马赛克的功能。具体的步骤如下: 1. 使用标准IO函数打开并读取图片,将其存储为一个二维的像素矩阵。 2. 将像素矩阵按照一定的规则进行分块,例如将整张图片分成若干个大小相同的正方形区域。 3. 对于每个区域,将其的像素值替换为该区域内所有像素值的平均值。 4. 将处理后的像素矩阵重新写入到一个新的图片文件。 下面是一个简单的示例代码,实现了将图片分成 4x4 的正方形区域,并将每个区域的像素值替换为该区域内所有像素值的平均值: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <math.h> #define BLOCK_SIZE 4 typedef struct { int r; int g; int b; } pixel_t; int main(int argc, char **argv) { if (argc != 3) { printf("Usage: %s <input_file> <output_file>\n", argv[0]); exit(1); } // Open input file FILE *input_file = fopen(argv[1], "rb"); if (!input_file) { printf("Error: cannot open input file.\n"); exit(1); } // Read header of input file char header[54]; fread(header, 1, 54, input_file); // Get image width, height, and number of bytes per pixel int width = *(int*)&header[18]; int height = *(int*)&header[22]; int bytes_per_pixel = *(int*)&header[28] / 8; // Allocate memory for input and output images pixel_t **input_image = malloc(height * sizeof(pixel_t*)); for (int i = 0; i < height; i++) { input_image[i] = malloc(width * sizeof(pixel_t)); } pixel_t **output_image = malloc(height * sizeof(pixel_t*)); for (int i = 0; i < height; i++) { output_image[i] = malloc(width * sizeof(pixel_t)); } // Read input image for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { pixel_t pixel; fread(&pixel, bytes_per_pixel, 1, input_file); input_image[i][j] = pixel; } } // Process input image block by block for (int i = 0; i < height; i += BLOCK_SIZE) { for (int j = 0; j < width; j += BLOCK_SIZE) { // Compute average pixel value for current block pixel_t avg_pixel; int num_pixels = 0; for (int x = i; x < i + BLOCK_SIZE; x++) { for (int y = j; y < j + BLOCK_SIZE; y++) { if (x < height && y < width) { avg_pixel.r += input_image[x][y].r; avg_pixel.g += input_image[x][y].g; avg_pixel.b += input_image[x][y].b; num_pixels++; } } } avg_pixel.r /= num_pixels; avg_pixel.g /= num_pixels; avg_pixel.b /= num_pixels; // Replace pixel values in current block with average pixel value for (int x = i; x < i + BLOCK_SIZE; x++) { for (int y = j; y < j + BLOCK_SIZE; y++) { if (x < height && y < width) { output_image[x][y] = avg_pixel; } } } } } // Write output image FILE *output_file = fopen(argv[2], "wb"); fwrite(header, 1, 54, output_file); for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { fwrite(&output_image[i][j], bytes_per_pixel, 1, output_file); } } // Free memory for (int i = 0; i < height; i++) { free(input_image[i]); free(output_image[i]); } free(input_image); free(output_image); // Close files fclose(input_file); fclose(output_file); return 0; } ``` 注意,这里使用了一个简单的分块规则,即将整张图片分成若干个大小相同的 4x4 的正方形区域。实际应用,可以根据具体需求选择不同的分块规则。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值