【问题标题】:File reading wrong value文件读取错误值
【发布时间】:2017-07-09 09:00:24
【问题描述】:

我不知道为什么会这样。我有一个结构可以完美地打印到文件中,但是当我尝试读出该文件时,我得到的东西甚至与实际存在的内容都不接近。写/读部分:

int save_data(){
    char enter = 0;
    int response;
     while(true){
            printf("1. Add new player\n2. View player data\n3. Return to main");
            printf("\nSelection: ");
            scanf("%d", &response);
                if (response == 1){
                     FILE* PlayerFile = fopen("players.txt","w");
                     int i = 0;

                     for (i = 0; i < 1; i++){
                     struct player_info aPlayer = create_player();
                     fprintf(PlayerFile, "Name: %s\nLevel: %d\nStrength Mod: %d\nDexterity Mod: %d\nConstitution Mod: %d\nIntelligence Mod: %d\nWisdom Mod: %d\nCharisma Mod: %d\n", aPlayer.name, aPlayer.Level, aPlayer.Str, aPlayer.Dex, aPlayer.Con, aPlayer.Int, aPlayer.Wis, aPlayer.Cha);
                     }
                     fclose(PlayerFile);
                     return 0;
                     }

                else if (response == 2){
                    struct player_info aPlayer;{
                        char name[30];
                        int Level, Str, Dex, Con, Int, Wis, Cha;
                        };
                    FILE* PlayerFile = fopen("players.txt","r");
                    for (int i = 0; i < 1; i++){
                        struct player_info create_player;
                        fscanf(PlayerFile, "Name: %s\nLevel: %d\nStrength Mod: %d\nDexterity Mod: %d\nConstitution Mod: %d\nIntelligence Mod: %d\nWisdom Mod: %d\nCharisma Mod: %d\n", aPlayer.name, &aPlayer.Level, &aPlayer.Str, &aPlayer.Dex, &aPlayer.Con, &aPlayer.Int, &aPlayer.Wis, &aPlayer.Cha);
                        printf("\nName: %s\nLevel: %d\nStr mod: %d\nDex mod: %d\nCon mod: %d\nInt mod: %d\nWis mod: %d\nCha mod: %d\n\n", aPlayer.name, &aPlayer.Level, &aPlayer.Str, &aPlayer.Dex, &aPlayer.Con, &aPlayer.Int, &aPlayer.Wis, &aPlayer.Cha);
                    }

                    fclose(PlayerFile);
                }
                else if (response == 3){
                false;
                break;}
}
}

文件中实际存在的输入:

Name: Hamfast Drummond
Level: 9
Strength Mod: 8
Dexterity Mod: 7
Constitution Mod: 6
Intelligence Mod: 5
Wisdom Mod: 4
Charisma Mod: 3

打印上面的结果:

Name: Hamfast
Level: 6422172
Str mod: 6422176
Dex mod: 6422180
Con mod: 6422184
Int mod: 6422188
Wis mod: 6422192
Cha mod: 6422196

现在,我意识到这一行在所有变量之前都缺少&amp;,但是当我添加它打印到文件中的内容是相同的错误数字并且在这种情况下读出是正确的,但它是没有将我放入的内容打印到文件中。

作为一个附带问题,如果允许我合二为一,我还希望它打印全名,而不仅仅是第一个,但我不知道该怎么做。

【问题讨论】:

  • response == 3 你需要return false;,而不仅仅是false;
  • 这将消除事后休息的需要。我一直想知道为什么它没有休息就不能工作。感谢您清除它。
  • 未使用的 struct player_info create_player;{ char name[30]; int Level, Str, Dex, Con, Int, Wis, Cha; };
  • @bansi 那么那些不需要在那里吗?我将它们包括在内是因为我不确定它们是否有必要,只是为了安全。
  • 仅供参考:或者您可以使用 fread 从文件中一次性读取整个结构。检查How to fread() structs?

标签: c file-io


【解决方案1】:

printf 想要带有 %d 格式说明符的值,而 scanf 想要引用

这个:

printf("\nName: %s\nLevel: %d\nStr mod: %d\nDex mod: %d\nCon mod: %d\nInt mod: %d\nWis mod: %d\nCha mod: %d\n\n", aPlayer.name, &aPlayer.Level, &aPlayer.Str, &aPlayer.Dex, &aPlayer.Con, &aPlayer.Int, &aPlayer.Wis, &aPlayer.Cha);

必须

printf("\nName: %s\nLevel: %d\nStr mod: %d\nDex mod: %d\nCon mod: %d\nInt mod: %d\nWis mod: %d\nCha mod: %d\n\n", aPlayer.name, aPlayer.Level, aPlayer.Str, aPlayer.Dex, aPlayer.Con, aPlayer.Int, aPlayer.Wis, aPlayer.Cha);

换句话说,您正在(严重)打印这些变量的地址,而不是它们的值。

【讨论】:

    【解决方案2】:
    printf("\nName: %s\nLevel: %d\nStr mod: %d\nDex mod: %d\nCon mod: %d\nInt mod: %d\nWis mod: %d\nCha mod: %d\n\n", aPlayer.name, aPlayer.Level, aPlayer.Str, aPlayer.Dex, aPlayer.Con, aPlayer.Int, aPlayer.Wis, aPlayer.Cha);
    

    你正在打印你从文件中读取的地址

    【讨论】:

      【解决方案3】:
      1. 关于读全名:

      使用规则%[^\n]\n 而不是%s\n。这将读取除换行符之外的所有内容,并为您提供全名。

      1. printf 不应使用&amp;&amp; 用于获取给定变量的地址。所以只有在使用 scanf 时才使用&amp;,因为我们想将值存储在地址中。使用 printf 时,只使用变量名,因为您需要该值。

      【讨论】:

      • 感谢您解决名称问题以及何时使用&amp;。和往常一样,在问了一些事情之后,我自己没有注意到它而感到有点愚蠢,但现在我知道并且下次可以做到这一点。这里有很多好的答案。感谢大家的帮助和快速回复!现在修好了。
      • 发生在我们所有人身上,你可以做的是尝试阅读编译器抛出的错误,看看你是否可以使用它进行调试。
      • 我没有得到任何编译器错误,因为它在技术上是正确的,只是没有做我认为应该做的事情。虽然我可能应该使用一些错误扩展器或类似-pedantic 以及我见过的其他一些东西。不确定他们都在做什么,但获得额外的信息不会有什么坏处。
      • 是的,他们很痛苦。再次感谢您所做的一切。
      【解决方案4】:

      发布的代码包含许多问题,如其他答案和问题的 cmets 中所述。

      这是一个干净地编译并实现建议更正的代码版本:

      #include <stdio.h>
      #include <stdbool.h>
      
      
      
      struct player_info
      {
          char name[30];
          int Level, Str, Dex, Con, Int, Wis, Cha;
      };
      
      struct player_info create_player( void );
      
      int save_data( void );
      
      int save_data( void )
      {
          //char enter = 0;
          int response;
      
           while(true)
           {
                  printf("1. Add new player\n"
                         "2. View player data\n"
                         "3. Return to main");
                  printf("\nSelection: ");
      
                  if( 1 != scanf("%d", &response) )
                  {
                      perror( "scanf failed" );
                      return 1;
                  }
      
                  if (response == 1)
                  {
                       FILE* PlayerFile = fopen("players.txt","r");
                       if( NULL == PlayerFile )
                       {
                           perror( "fopen for truncate and write failed" );
                           return 1;
                       }
      
                       int i = 0;
      
                       struct player_info aPlayer = create_player();
                       fprintf(PlayerFile, "Name: %s\nLevel: %d\nStrength Mod: %d\nDexterity Mod: %d\nConstitution Mod: %d\nIntelligence Mod: %d\nWisdom Mod: %d\nCharisma Mod: %d\n", aPlayer.name, aPlayer.Level, aPlayer.Str, aPlayer.Dex, aPlayer.Con, aPlayer.Int, aPlayer.Wis, aPlayer.Cha);
      
                       fclose(PlayerFile);
                       return 0;
                  }
      
                  else if (response == 2)
                  {
                      struct player_info aPlayer;
      
                      FILE* PlayerFile = fopen("players.txt","r");
                      if( NULL == PlayerFile )
                      {
                          perror( "fopen for reading failed" );
                          return 1;
                      }
      
                      fscanf(PlayerFile, "Name: %s\nLevel: %d\nStrength Mod: %d\nDexterity Mod: %d\nConstitution Mod: %d\nIntelligence Mod: %d\nWisdom Mod: %d\nCharisma Mod: %d\n",
                          aPlayer.name,
                          &aPlayer.Level,
                          &aPlayer.Str,
                          &aPlayer.Dex,
                          &aPlayer.Con,
                          &aPlayer.Int,
                          &aPlayer.Wis,
                          &aPlayer.Cha);
                      printf("\nName: %s\nLevel: %d\nStr mod: %d\nDex mod: %d\nCon mod: %d\nInt mod: %d\nWis mod: %d\nCha mod: %d\n\n",
                          aPlayer.name,
                          aPlayer.Level,
                          aPlayer.Str,
                          aPlayer.Dex,
                          aPlayer.Con,
                          aPlayer.Int,
                          aPlayer.Wis,
                          aPlayer.Cha);
      
      
                      fclose(PlayerFile);
                  }
      
                  else if (response == 3)
                  {
                      //false;
                      break;
                  }
          }
          return 0;
      }
      

      但是,我强烈建议不要将所有字段标签文本放在文件中,因为它只会在尝试从程序中读取文件时产生问题。

      请注意,程序在任何单个操作后返回,因此文件不能包含比单个播放器信息更多的内容。

      【讨论】:

        猜你喜欢
        • 2012-10-12
        • 2013-07-05
        • 2018-02-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多