【问题标题】:C Null character causing problems with program behaviourC 空字符导致程序行为问题
【发布时间】:2014-06-26 04:21:48
【问题描述】:

我遇到的问题是这个程序是菜单驱动的。当我输入字母“i”时,将输入input 数组,其大小为MAX_LENGTH+1。通过GDB我发现“i”输入到input数组的第0个索引中,其余空格输入NULL_CHAR字符。无论如何,当我为插入菜单按“i”时,我看到了一个告诉我输入值的字段。我输入任何整数并按inter。它没有受到“命令?:”字段的欢迎并给我一个输入条目的机会,而是立即告诉我我的输入无效并告诉我再次输入命令。这就是我的意思:

Commands are I (insert), D (delete), S (search by name),
  V (search by value), P (print), Q (quit).

Command?: i
45

Command?: 
Invalid command.
Commands are I (insert), D (delete), S (search by name),
  V (search by value), P (print), Q (quit).


Command?: 

我发现发生这种情况的原因是因为当再次调用safegets函数时,由于某种原因,函数safegets中的局部变量c的值为NULL_CHAR,大概是因为所有的输入字符数组中的其他值的所有其他条目为NULL_CHAR。我不明白为什么c 会自动分配NULL_CHAR 的值,因为在while 循环中,因为有一条语句c = getchar() 应该再次要求我输入。但是由于某种原因,在每次输入之后,c 的默认值变为 NULL_CHAR,并在下次调用 safegets 时要求您输入。

这是我想要的输出:

Commands are I (insert), D (delete), S (search by name), 
  V (search by value), P (print), Q (quit). 
 
Command?: I 
  value: 50000 
 
Command?: I
  value: 

这里是主要功能:

const int MAX_LENGTH = 1023;
const char NULL_CHAR = '\0';
const char NEWLINE = '\n';


    int main (void)
    { 
        const char bannerString[]
            = "Personal Team Maintenance Program.\n\n";
        const char commandList[]
            = "Commands are I (insert), D (delete), S (search by name),\n"
              "  V (search by value), P (print), Q (quit).\n";

        // Declare linked list head.
        //   ADD STATEMENT(S) HERE TO DECLARE LINKED LIST HEAD.


        // announce start of program
        printf("%s",bannerString);
        printf("%s",commandList);

        char response;
        char input[MAX_LENGTH+1];
        int value;
        do
        {
            printf("\nCommand?: ");
            safegets(input,MAX_LENGTH+1);
            // Response is first char entered by user.
            // Convert to uppercase to simplify later comparisons.
            response = toupper(input[0]);

            if (response == 'I')
            {
                // Insert a player entry into the linked list.
                // Maintain the list in correct order (G, D, M, S).
                //   ADD STATEMENT(S) HERE

                // USE THE FOLLOWING PRINTF STATEMENTS WHEN PROMPTING FOR DATA:
                // printf("  family name: ");
                // printf("  first name: ");
                // printf("  position: ");
                   printf(" value: ");
                   scanf("%d", value);






            }
            else if (response == 'D')
            {
                // Delete a player from the list.

                printf("\nEnter family name for entry to delete: ");

                //   ADD STATEMENT(S) HERE

            }
            else if (response == 'S')
            {
                // Search for a player by family name.

                printf("\nEnter family name to search for: ");

                //   ADD STATEMENT(S) HERE

            }
            else if (response == 'V')
            {
                // Search for players that are worth less than or equal a value.

                printf("\nEnter value: ");

                //   ADD STATEMENT(S) HERE

            }
            else if (response == 'P')
            {
                // Print the team.

                //   ADD STATEMENT(S) HERE

            }
            else if (response == 'Q')
            {
                ; // do nothing, we'll catch this case below
            }
            else 
            {
                // do this if no command matched ...
                printf("\nInvalid command.\n%s\n",commandList);
            }
        } while (response != 'Q');

        // Delete the whole linked list that hold the team.
        //   ADD STATEMENT(S) HERE


        // Print the linked list to confirm deletion.
        //   ADD STATEMENT(S) HERE


        return 0;
    }

正在调用的辅助函数:

void safegets (char s[], int arraySize)
{
    int i = 0, maxIndex = arraySize-1;
    char c;
    while (i < maxIndex && (c = getchar()) != NEWLINE)
    {
        s[i] = c;
        i = i + 1;
    }
    s[i] = NULL_CHAR;
}

【问题讨论】:

  • 您为什么要尝试将\0\n 隐藏在一些自定义名称后面?虽然避免使用魔法常数是一种很好的做法,但它们并非如此。
  • 这通常不称为“空字符”,而是“终止空字符”。
  • 请只提供最少量的代码来证明您的问题。

标签: c arrays


【解决方案1】:

您的代码很好。你需要改变

scanf("%d", value); 
//          ^Place & before the argument value because scanf expect pointer as its argument

scanf("%d", &value);

【讨论】:

    【解决方案2】:

    如果修复 ze code fer ewe

          else 
            {
                // do this if no command matched ...
                if (response != '\0')
                  printf("\nInvalid command.\n%s\n",commandList);
            }
    

    【讨论】:

      【解决方案3】:

      我认为您的代码的问题在于您在调用scanf 后没有清空输入缓冲区(例如输入 if 和 'I' 并读取 'value'。每次调用 scanf你仍然会在输入缓冲区中有回车和/或换行符。下一次调用safegets 会看到输入仍在输入缓冲区中并读取它。要修复它,请在每次调用scanf 后清空输入缓冲区:

      char strip;
      
      . . .
      
      if (response == 'I')
      {
          printf(" value: ");
          scanf("%d", value);
      
          /* empty the input buffer after scanf */
          do {
              strip = getchar();
          } while (strip != '\n');
      
          printf
      
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-05-09
        • 2021-05-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-11-03
        • 1970-01-01
        相关资源
        最近更新 更多