C 程序在 if/else 之后终止,或者如果我使用 fputs/fgets 则重复

标签 c stdin scanf fgets fputs

我对 C 非常陌生,并且涉足 Objective-C、AppleScript 和 HTML/CSS。我确信我的问题很容易解决。我正在尝试编写一些内容,允许我输入源数据并以某种方式将其排序为输出(在本例中为引用)。基本上,我想将名称、标题、出版商等保存为变量并按特定顺序打印它们。

问题是:这里的代码终止得太早,当我将 fputs 和 fgets 与 stdout 和 stdin 一起使用时,它会卡住并永远询问相同的问题。我错过了什么?

int source_type;
int NumberofAuthors;
char AuthorName1[20];
char AuthorName2[20];
char AuthorName3[20];
char title[20];
char url[100];
char publishingCity[20];
char publisher[20];
char yearPublished[20];
char pageNumbers[20];
int valid;

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");
}

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 people to write a book.\n" );
    }

    if ( NumberofAuthors == 1 ) {
        printf( "Author's name: " );
        scanf("%c", &AuthorName1);

    } 
    if (NumberofAuthors == 2) {
        printf("First author's name: " );
        scanf("%c", &AuthorName2);
        printf("Second author's name: " );
        scanf("%c", &AuthorName3);
    }
    else {
        valid = 0;
    }

    printf("Book title: " );
    fgets(title, sizeof(title), stdin);

    printf("Publication city: " );
    fgets(publishingCity, sizeof(publishingCity), stdin);


    } 


return 0;

最佳答案

在程序开始时:

if (source_type == 'a') {
    valid = 1;
} else {
    printf("Invalid source selection");
}

如果 source_type 无效,valid 仍然包含垃圾值,并且使用未初始化的变量是未定义的行为。继续前进。

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);
    }
    //...

您从未将valid重置为0。您应该考虑对 while 循环的该部分使用 switch()。它使它更容易阅读。

还有

if ( NumberofAuthors == 1 ) {
    printf( "Author's name: " );
    scanf("%c", &AuthorName1);

} 
if (NumberofAuthors == 2) {
    printf("First author's name: " );
    scanf("%c", &AuthorName2);
    printf("Second author's name: " );
    scanf("%c", &AuthorName3);
}
else {
    valid = 0;
}

我希望您意识到,如果NumberofAuthors == 1else部分将被执行并设置valid = 0。这是因为 else 只粘在最接近的 if 上,且仅粘在最接近的 if 上。

我猜你使用 fgets 等来避免溢出。好的。请参阅 scanf 上的技巧。在这里阅读更多信息:http://www.cplusplus.com/reference/clibrary/cstdio/scanf/

尝试一下:

int main(int argc, char* argv[])
{
    char source_type;
    int NumberofAuthors;
    char AuthorName1[20];
    char AuthorName2[20];
    char AuthorName3[20];
    char title[20];
    char url[100];
    char publishingCity[20];
    char publisher[20];
    char yearPublished[20];
    char pageNumbers[20];
    int valid;

    printf("Welcome to Jackson's Chicago Manual of Style Auto-Footnoter.\n");

    printf("Choose source type:\n a.Book");
    scanf("%c" , &source_type);

    if (source_type == 'a') {
        valid = 1;
    } else {
        printf("Invalid source selection");
        valid = 0;
    }

    while ( valid == 1 && source_type == 'a' )
    {
        //Reset
        valid = 0;

        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 people to write a book.\n" );
            continue;
        }

        switch( NumberofAuthors )
        {
        case 1:
            printf( "Author's name: " );
            scanf("%19s", AuthorName1);
            break;

        case 2:
            printf("First author's name: " );
            scanf("%19s", AuthorName2);
            printf("Second author's name: " );
            scanf("%19s", AuthorName3);
            break;

        default:
            valid = 0;
            break;
        }

        if(valid)
        {
            printf("Book title: " );
            scanf("%19s" , title);

            printf("Publication city: " );
            scanf("%19s" , publishingCity );
        }

    } 
    return 0;
}

关于C 程序在 if/else 之后终止,或者如果我使用 fputs/fgets 则重复,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8017015/

相关文章:

c - 如何从文件中读取带有特殊字符的浮点型数字

c - scanf 之后 fgets 不起作用

c - 操纵变量的地址来存储较小的类型?

c - C 输出中的随机字节

c - 从函数返回一个指向 main 的指针

c++ - 在 OSX 上的共享库中定义 main

c - C 程序中的 stdout 转义查询和 stdin 冲突(无 ncurses)

java - 为什么我们不能一次从 System.in 中读取一个字符?

c - 在 C 中反转标准输入

c - 如何允许使用 scanf 输入空格?