首先看一下你的代码,想想当有人进入超过100个字符一个字会发生什么 - >未定义行为。如果你使用缓冲区进行输入,你的总是必须加上检查所以你不要溢出这个缓冲区。
但是,当你直接打印字符时,为什么你需要一个缓冲区呢?您展示的方法完全没有必要。试试这个:
#include
#include
int main()
{
int ch;
int firstChar = 1; // needed to also accept PascalCase
while((ch = getchar())!= EOF)
{
if(isupper(ch))
{
if (!firstChar) putchar('_');
putchar(tolower(ch));
} else
{
putchar(ch);
}
firstChar = 0;
}
}
附注:我改变了ch类型int。这是因为getchar()返回int,putchar(),isupper()和islower()取int,它们都使用值unsigned char或EOF。由于char被允许进行签名,因此在具有签名为char的平台上,您会收到未定义的行为,调用这些函数的负数为char。我知道,这有点复杂。解决此问题的另一种方法是,在调用将unsigned char的值作为int的函数时,始终将您的char设置为unsigned char。
当你使用一个缓冲区,它现在也没用,你可能有兴趣有是一个可能的解决方案充分利用缓冲的:读,写一次一整行。这比为每个字符调用一个函数稍微有效一些。下面是一个例子这样做:
#include
static size_t toSnakeCase(char *out, size_t outSize, const char *in)
{
const char *inp = in;
size_t n = 0;
while (n < outSize - 1 && *inp)
{
if (*inp >= 'A' && *inp <= 'Z')
{
if (n > outSize - 3)
{
out[n++] = 0;
return n;
}
out[n++] = '_';
out[n++] = *inp + ('a' - 'A');
}
else
{
out[n++] = *inp;
}
++inp;
}
out[n++] = 0;
return n;
}
int main(void)
{
char inbuf[512];
char outbuf[1024]; // twice the lenght of the input is upper bound
while (fgets(inbuf, 512, stdin))
{
toSnakeCase(outbuf, 1024, inbuf);
fputs(outbuf, stdout);
}
return 0;
}
这个版本也避免了isupper()和tolower(),但牺牲了便携性。它仅适用于如果字符编码的顺序是字母,并且在小写字母之前有大写字母,则可以使用。对于ASCII,这些假设成立。请注意,被认为是(大写)的字母也可能取决于语言环境。上述程序仅适用于英文字母A-Z。