Что ж, вы слишком усложнили вещи, самостоятельно буферизовав входные данные, в то время как вы могли бы использовать 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;
}
Этот фрагмент кода будет делать именно то, что вы пытаетесь, прозрачно буферизуя ввод и вывод, и, таким образом, переносимый в другие среды с различными кодировками символов. Без сомнения, лучший способ сделать это:
#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); */
}
}
}