字符字符串使我的while循环退出?

时间:2018-07-16 07:51:37

标签: c arrays string

除情况4之外,所有内容均适用于此代码。G<--textureCoord_to_word_coordinates--T<--?????---I语句在其中检查ifname是否为空。但是,如果array和char array不为空,则name循环将退出整个程序。基本上,它不会打印摘要。如果我在while语句中删除了“名称”,则可以正常运行。一旦将其重新插入,就会导致同样的问题。

我把字符串叫错了吗?

printf

3 个答案:

答案 0 :(得分:1)

首先,警告不可忽略。当我编译代码时,我自己的编译器(CLang)像圣诞树一样闪烁,并且所有警告均是真实的代码错误。这是您的程序的最低固定版本。但是,一旦可行,我建议您将其提交到Code Review上,以获取更多有关如何改善编码风格的深入评论。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define true 1                // not incorrect but uncommon since stdbool.h have existed
#define false 0

float calculate_percent( float score, float max_score );
float getAvg( float num1, float num2, float num3 );
char getGradeLetter( float score );
void print_line( char symbol, int count );

int main()
{
    char name[20] = { 0 };               // ok initializes the full array to `\0` chars
    int scores[3] = { 0 };
    float avg = 0;
    int reply;

    print_line( '*', 10 );

    while ( true )                   // while (1) would be idiomatic C
    {
        print_line( '*', 10 );

        printf( "\nChose an option.\n" );
        printf( "1.Enter user name.\n2.Enter exam scores.\n3.Display average exam scores.\n4.Display Summary.\n5.Quit\n" );
        scanf( "%d", &reply );

        switch ( reply )
        {
            case 1:
                printf( "Enter name.\n" );
                scanf( "%s", name ); // an array decays to a pointer to its first element
                break;

            case 2:
                for ( int i = 0; i < 3; i++ )
                {
                    printf( "Enter a score.\n" );
                    scanf( "%d", &scores[i] );     /* dangerous because you do not control
                        the retun value: what will happen is an alphabet is typed? */
                }
                break;

            case 3:
                // you must test the FIRST element of the string, not one past end
                // and never mix && and || without ()
                if ( name[0] == 0 || scores[0] == 0 || scores[1] == 0 || scores[2] == 0 )
                {
                    printf( "You havent entered the scores.\n" );
                }
                else
                {
                    avg = getAvg( scores[0], scores[1], scores[2] );
                    printf( "Your average is %.2f\n", avg );
                }
                break;

            case 4:
                // same remark as above...
                if ( name[0] == 0 || scores[0] == 0 || scores[1] == 0 || scores[2] == 0 )
                {
                    printf( "Name or scores are empty.\n" );
                }
                else
                {
                    printf( "Hello %s, your scores are %d %d %d.\n", name, scores[0], scores[1], scores[2] );
                    // %d is for an int, use %f for a float
                    printf( "your average is %.2f with a letter of grade %c.\n", avg, getGradeLetter( avg ) );
                }
                break;

            case 5:
                exit( 0 );
        }
    }

    // getchar();           // refrain! good IDE allow a breakpoint on the return in debug mode
                            // and do not close the window in non debug mode
    return 0;
}

float calculate_percent( float score, float max_score )
{
    return score / max_score * 100;
}

float getAvg( float num1, float num2, float num3 )
{
    return ( num1 + num2 + num3 ) / 3;
}

char getGradeLetter( float score )
{
    char grade_letter = 'F';            // you MUST initialize if at least a branch sets no value

    if ( score >= 90 )
    {
        grade_letter = 'A';
    }
    else if ( score >= 80 )
    {
        grade_letter = 'B';
    }
    else if ( score >= 70 )
    {
        grade_letter = 'C';
    }
    else if ( score >= 60 )
    {
        grade_letter = 'D';
    }
    else if ( score > 0 && score < 59 )
    {
        printf( "you failed the test.\n\n" );
    }

    return grade_letter;
}

void print_line( char symbol, int count )
{
    for ( int i = 0; i < count; i++ )
    {
        printf( "%c", symbol );
    }
}

答案 1 :(得分:0)

在情况4的陈述中:

printf("Hello %s, your scores are %d %d %d.\n", name[20], scores[0], scores[1], scores[2]);

name[20]替换为名称。 name保存数组名称的起始地址指针,这是print函数打印char数组内容所需要的。所以您的代码应该像这样

printf("Hello %s, your scores are %d %d %d.\n", name, scores[0], scores[1], scores[2]);

答案 2 :(得分:0)

  • 数组索引从0开始,这意味着name [0]是第一个元素,name [19]是最后一个元素。 char name [20] 定义了一个由20个元素组成的字符数组,这意味着它可以容纳19个字符串以及结尾的NUL。
  • 在C语言中,类型为 char 的数组用于存储字符串,并且字符串以NUL终止,这意味着字符串的最后一个字节(char)必须为不可打印的值'\ 0',以使标准字符串库功能和printf正常工作。
  • 如先前的评论者所述,&name[20]是指向数组后的第一个字节的指针。尽管name数组的内存是在堆栈上自动分配的,但是name[20]不在此内存块中,访问此字节将导致未定义的行为。

换句话说:

  • 当您调用scanf时,请执行以下操作:scanf(“%s”,&name [0]);或仅仅是这样:scanf(“%s”,name);
  • 确保使用scanf读取的字符串的长度小于19个字符,或者增加名称数组的大小。这不是您的当务之急,但是使用scanf读取用户输入通常是不安全的(有关缓冲区溢出的更多信息,请阅读here
  • 要检查您的字符串是否为“空”,请使用: name[0] == '\0'而非name[20] == 0
  • 在打印语句中,使用printf("%s...", name,...)代替printf("%s...", name[20],...)