我有一个名为abc
的程序。
当我运行以下命令时:
$ ./abc < infile
我得到以下输出:
ijklm
然而,当我跑步时:
$ ./abc < infile > outfile
$ cat outfile
我得到了这个输出:
ijkoo
现在,我假设这是我的程序的错误。但是,无论我的程序在做什么,我都不知道这是怎么回事。
修改
既然我知道这是可能的,我很好奇我的程序中是什么导致了这一点。
我程序中的循环中有一个块包含:
byte = ascii_to_byte(asciibyte);
putchar(byte);
字节的类型为char
。
现在,如果我将putchar(byte)
更改为printf("%c", byte)
,则所有输出都保持不变。
但是,如果我将其更改为printf("%d", byte)
,则$ ./abc < infile
会输出:
105106107111111
这是与outfile
中的ascii字符的十进制表示形式。但它们并不是角色的十进制表示,因为它们刚刚被发送到stdout时实际出现了。我不明白为什么会出现这种差异。
编辑#2:
如果我将打印行更改为printf("%c\n", byte)
,则$ ./abc < infile
输出:
i
j
k
o
o
这与outfile中的内容一致。再一次,不确定区别是什么。
编辑#3
我刚刚在32位计算机上对此进行了测试,该程序正常运行:outputfile
包含ijklm
。奇怪的。
编辑#4
这是主要功能:
int main()
{
char asciibyte[8];
char byte;
int c; //Using int to avoid the EOF pitfall.
long charcount = 0;
while((c = getchar()) != EOF){
if(c != '0' && c != '1'){
continue;
}
asciibyte[charcount % 8] = c;
if(charcount % 8 == 7){
/*Testing revealed that at this point asciibyte does contain
what it should contain, eight ASCII ones and zeros representing
a byte read in from stdin*/
byte = ascii_to_byte(asciibyte);
/*Print statements such as:
printf("%d", byte);
printf("%c\n", byte);
reveal that the ascii_to_byte function works incorrectly on my
64 bit machine. However these statements:
putchar(byte);
printf("%c", byte);
make it appear as though the function operates as it should.
EXCEPT if i redirect that output to a file.*/
putchar(byte);
}
charcount++;
}
return 0;
}
这是ascii_to_byte函数:
char ascii_to_byte(char *asciibyte){
char byte;
int i;
for(i = 0; i < 8; ++i){
if(asciibyte[7-i] == '1'){
byte = byte | (1 << i);
}
}
return byte;
}
最终编辑
我注意到我应该将字节初始化为0x00。问题解决了。我为什么这么迟钝?我会给那些能够具体解释这是如何导致问题的人给出答案。
答案 0 :(得分:3)
这种奇怪的行为,根据看似无关的变化来来去去,可能表明你的程序不应该从内存中读取或写入内存,并且行为随着代码的其他部分的不同而变化堆栈和/或堆。
我会仔细检查你的代码是否有错误,比如缓冲区溢出,返回堆栈变量指针的函数等等。
使用调试器逐步调试代码可能会很有效(或者如果你运气不好,它可能会再次改变行为!)。
你见过几件有趣的事情:
stdout
的重定向如何影响任何事情?也许是因为它导致C库的行为有点不同:流使用不同的缓冲模式,具体取决于它是否连接到终端设备(请参阅GNU libc documentation或C99 §7.9.13第7段。
当putchar(byte)
和printf("%c", byte)
确实改变行为时,为什么将printf("%d", byte)
更改为printf("%c\n", byte)
不会改变任何内容?也许是因为编译器自动将printf("%c", byte)
重写为效率更高的putchar(byte)
- 即使没有启用优化,通常会执行此操作 - 而printf("%d", byte)
和printf("%c\n", byte)
确实如此将被编译为printf()
的调用。
答案 1 :(得分:1)
当然可以 - 程序可以检查它是否正在写入终端并写入与写入管道时写入的内容不同的内容。
答案 2 :(得分:1)
正如您所说,byte
未初始化,因此可能会发生任何。
可能发生的事情之一是byte
“从0开始”并将其值从函数调用保持到函数调用(就好像它被声明为static
)。
in binary ... byte | c (bin) | byte | c -----------+--------------+-------------- 00000000 | i (01101001) | 01101001 (i) 01101001 | j (01101010) | 01101011 (k) * strange you get 'j', but anything can happen :) 01101011 | k (01101011) | 01101011 (k) 01101011 | l (01101100) | 01101111 (o) 01101111 | m (01101101) | 01101111 (o)
答案 3 :(得分:0)
Neil Butterworth说的话。该函数称为isatty
。
if (isatty(STDOUT)) printf("I am printing to the terminal!\n");
此外,在测试内容时,您可能已经完成了:
$ ./abc < infile > infile
意外。因此,您可能希望快速检查,infile
确实包含相同的数据。