Вы используете %c
для чтения имен; это не хорошо. Вы передаете адрес массива, а не указатель на первый элемент массива; это тоже не хорошо. Вы растоптаны повсюду и оставляете себя с неопределенными проблемами поведения.
«Очевидное» исправление - использовать %s
и отказаться от &
перед именами массивов, но вы не должны поддаваться очевидному, так как это неправильно. У большинства авторов есть пробел между именем и фамилией (или инициалами и фамилией), и %s
останавливается на первом пробеле. Вам нужно использовать fgets()
для чтения имен, но не забудьте удалить завершающий перевод строки.
Мне не совсем понятно, почему у вас есть одно имя автора в «AuthorName1», но двойные авторы идут в «AuthorName2» и «AuthorName3»; Я бы предпочел использовать «имя 1» для первого автора независимо от. В самом деле, может быть, лучше иметь массив имен авторов, который будет легче обобщать.
Когда я компилирую ваш код (оборачивая его в int main(void) {
и }
и включая <stdio.h>
, я получаю предупреждения компиляции:
xx.c: In function ‘main’:
xx.c:43: warning: format ‘%c’ expects type ‘char *’, but argument 2 has type ‘char (*)[20]’
xx.c:43: warning: format ‘%c’ expects type ‘char *’, but argument 2 has type ‘char (*)[20]’
xx.c:48: warning: format ‘%c’ expects type ‘char *’, but argument 2 has type ‘char (*)[20]’
xx.c:48: warning: format ‘%c’ expects type ‘char *’, but argument 2 has type ‘char (*)[20]’
xx.c:50: warning: format ‘%c’ expects type ‘char *’, but argument 2 has type ‘char (*)[20]’
xx.c:50: warning: format ‘%c’ expects type ‘char *’, but argument 2 has type ‘char (*)[20]’
Я переписал код, чтобы использовать функцию для обработки запроса и чтения строк, таким образом:
#include <assert.h>
#include <stdio.h>
#include <string.h>
static int get_string(const char *prompt, char *buffer, size_t bufsiz)
{
char *nl;
printf("%s: ", prompt);
fflush(0);
if (fgets(buffer, bufsiz, stdin) == 0)
return EOF; /* Read error - EOF */
if ((nl = strchr(buffer, '\n')) == 0)
{
fprintf(stderr, "Overlong string entered!\n");
return EOF;
}
*nl = '\0';
return 0;
}
int main(void)
{
int source_type;
int NumberofAuthors;
char AuthorName1[20];
char AuthorName2[20];
char title[20];
char publishingCity[20];
int valid = 0;
int c;
printf("Welcome to Jackson's Chicago Manual of Style Auto-Footnoter.\n");
fputs("Choose source type:\n a.Book\n b.Journal\n c.Article\n d.Website\n ", stdout);
source_type = getchar();
if (source_type == 'a')
valid = 1;
else
{
printf("Invalid source selection");
return(1);
}
/* Lucky that scanf() skips over the newline in search of digits! */
while (valid == 1 && source_type == 'a')
{
printf("Number of authors [1 or 2]");
scanf("%d", &NumberofAuthors);
if (NumberofAuthors > 0 && NumberofAuthors < 3)
{
valid = 1;
printf("Got it, %d author(s).\n", NumberofAuthors);
}
else
{
printf("That's not enough (or too many) people to write a book.\n");
break;
}
/* Gobble to newline */
while ((c = getchar()) != EOF && c != '\n')
;
if (NumberofAuthors == 1)
{
if (get_string("Author's name", AuthorName1, sizeof(AuthorName1)) == EOF)
{
valid = 0;
break;
}
}
else
{
assert(NumberofAuthors == 2);
if (get_string("First author's name", AuthorName1, sizeof(AuthorName1)) == EOF ||
get_string("Second author's name", AuthorName2, sizeof(AuthorName2)) == EOF)
{
valid = 0;
break;
}
}
if (get_string("Book title", title, sizeof(title)) == EOF ||
get_string("Publication city", publishingCity, sizeof(publishingCity)) == EOF)
{
valid = 0;
break;
}
printf("Author 1: %s\n", AuthorName1);
if (NumberofAuthors == 2)
printf("Author 2: %s\n", AuthorName2);
printf("Book title: %s\n", title);
printf("Publication city: %s\n", publishingCity);
}
return 0;
}
Я сохранил флаг 'valid', но он действительно не окупается. Код проще и короче без него.