好吧,通过自己缓冲输入数据,您的事情变得过于复杂,而您可以使用 getchar() 和 putchar() 已经缓冲的函数。同样使用数字而不是字符文字,隐藏了代码的实际目标(转换为大写,反对在代码中添加减去奇怪的魔法值),并将其与 ASCII 字符代码环境联系起来:
#include <stdio.h>
int main()
{
int c;
while((c = getchar()) != EOF) {
if (c >= 'a' && c <= 'z') /* char literals are your friends */
c += 'A' - 'a'; /* also here */
putchar(c);
}
return 0;
}
这个 sn-p 代码将完全按照您的尝试执行,透明地缓冲输入和输出,并以一种可移植到具有不同字符编码的其他环境的方式。毫无疑问,更好的方法是:
#include <stdio.h>
#include <ctype.h>
int main()
{
int c;
while((c = getchar()) != EOF) {
putchar(toupper(c));
}
return 0;
}
如果你用一个大文本文件测试这两个程序,你会发现这个程序的响应比你写的那个更好,因为标准库已经自动为你选择了最佳的读写缓冲区大小,基于在传递给它的文件描述符上,而不是您在程序中使用的固定缓冲区大小(512 字节)。
在您的代码中,您将缓冲区指针传递给您的函数,它只会将其第一个字符大写...仅此而已,仅此而已,因此您只会获得每行的第一个字符(以防您的输入来自终端,因为输入在以规范模式从终端读取时在每一行结束)或每个 512 字节块的第一个字符,以防您从文件中读取。
为了让你的函数工作,你应该传递缓冲区和它的大小,因为它里面的实际读取数据量是未知的,你需要在里面放一个for循环来处理每个字符。 .或者在函数外做循环,对缓冲区的每个字符位置调用函数,由read(2)填充。
如果您想自己进行缓冲,如示例代码中所示,您必须输入实际读取字符的长度并转换例程中传递的数量,如下所示:
#include <unistd.h>
#include <stdio.h> /* for printing errors to stderr */
#include <string.h> /* for strerror */
#include <errno.h> /* for errno definition */
#define SIZE 512
void charToUpper(char *, size_t);
int main () {
ssize_t nread, nwritten;
char buf[SIZE];
while ((nread = read(0, buf , SIZE)) > 0) {
charToUpper(buf, nread);
nwritten = write(1, buf, nread);
if (nwritten < 0) { /* check for writing errors */
fprintf(stderr,
"Error: write: %s\n",
strerror(errno));
return 1; /* write error */
}
}
if (nread < 0) { /* check for reading errors */
fprintf(stderr,
"Error: read: %s\n",
strerror(errno));
return 2; /* read error */
}
return 0; /* no error */
}
void charToUpper(char *a, size_t sz){ /* better declare it void, as we don't return anything */
/* this code assumes uppercase chars and lower case are together in the
* char map, and contiguous (this is false in EBCDIC mappings) so better
* to use toupper(*a) in all cases */
for(;sz--; a++) { /* for every char in a, up to sz chars. */
if ((*a >= 'a') && (*a <= 'z')) { /* if *a is lower case letter */
*a += 'A' - 'a'; /* convert to uppercase */
/* better if you use *a = toupper(*a); */
}
}
}