在输出中有两行带有不应该出现的特殊字符。

huangapple go评论108阅读模式
英文:

Two lines in the output with special charachters that shouldn't be there

问题

以下是您提供的文本的翻译:

  1. 我有一个以这种格式列出歌曲的txt文件
  2. we will rock you
  3. queen
  4. 2:01
  5. 我需要将这些数据放入名为"elenco"的列表中,并使用以下结构:
  6. struct elenco{
  7. char titolo[30];
  8. char autore[30];
  9. int durata_in_sec;
  10. int rips;
  11. struct elenco *prossima;
  12. };
  13. 我尝试使用fscanf(fp, "%29[^\n]%*c", elenco->autore);(以此类推)存储数据,并使用简单的printf("%s\n", elenco->autore);输出,但输出正确,直到程序输出两行特殊字符,如下所示:
  14. > ?w
  15. > h(((( y
  16. 如果您想检查它,这是完整的程序
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <string.h>
  20. struct elenco{
  21. char titolo[30];
  22. char autore[30];
  23. int durata_in_sec;
  24. int rips;
  25. struct elenco *prossima;
  26. };
  27. int main()
  28. {
  29. FILE *fp;
  30. fp = fopen("musica.txt", "r");
  31. int i=0;
  32. int secondi, minuti;
  33. struct elenco *start = NULL;
  34. struct elenco *elenco = NULL;
  35. struct elenco *prec = NULL;
  36. while (!feof(fp))
  37. {
  38. elenco = malloc(sizeof(struct elenco));
  39. fscanf(fp, "%29[^\n]%*c", elenco->titolo);
  40. fscanf(fp, "%29[^\n]%*c", elenco->autore);
  41. fscanf(fp, "%d:%d", &minuti, &secondi);
  42. elenco->durata_in_sec = minuti*60+secondi;
  43. elenco->rips=1;
  44. elenco->prossima = NULL;
  45. if(i==0)
  46. {
  47. start = elenco;
  48. }
  49. else
  50. {
  51. prec->prossima = elenco;
  52. }
  53. prec = elenco;
  54. i++;
  55. }
  56. // 打印
  57. elenco = start;
  58. while(elenco!=NULL)
  59. {
  60. printf("%s\n", elenco->titolo);
  61. printf("%s\n", elenco->autore);
  62. printf("%d\n", elenco->durata_in_sec);
  63. printf("%d\n", elenco->rips);
  64. elenco = elenco->prossima;
  65. }
  66. fclose(fp);
  67. // 释放内存
  68. elenco = start;
  69. while (elenco != NULL) {
  70. struct elenco* temp = elenco;
  71. elenco = elenco->prossima;
  72. free(temp);
  73. }
  74. return 0;
  75. }

这是txt文件的内容:

we will rock you
queen
2:01
it's my life
bon jovi
3:46
we will rock you
queen
2:01
the show must go on
queen
4:36

  1. <details>
  2. <summary>英文:</summary>
  3. I have a txt with a list of songs in this format:
  4. we will rock you
  5. queen
  6. 2:01
  7. and i need to put those data in a list named &quot;elenco&quot; with this struct:

struct elenco{
    char titolo[30];
    char autore[30];
    int durata_in_sec;
    int rips;
    struct elenco *prossima;
};

  1. I tried to store the datas with `fscanf(fp, &quot;%29[^\n]%*c&quot;, elenco-&gt;autore);` (and so on) and the output with a simple `printf(&quot;%s\n&quot;, elenco-&gt;autore);` but the output is correct until the program outputs two lines with special characters like this:
  2. &gt; ?w
  3. &gt; h☻(☻(☻(☻(☻ y
  4. this is the full program if you want to check it

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct elenco{
char titolo[30];
char autore[30];
int durata_in_sec;
int rips;
struct elenco *prossima;
};

int main()
{
FILE *fp;
fp = fopen("musica.txt", "r");
int i=0;
int secondi, minuti;
struct elenco *start = NULL;
struct elenco *elenco = NULL;
struct elenco *prec = NULL;
while (!feof(fp))
{
elenco = malloc(sizeof(struct elenco));
fscanf(fp, "%29[^\n]%*c", elenco->titolo);
fscanf(fp, "%29[^\n]%c", elenco->autore);
fscanf(fp, "%d:%d", &minuti, &secondi);
elenco->durata_in_sec = minuti
60+secondi;
elenco->rips=1;
elenco->prossima = NULL;
if(i==0)
{
start = elenco;
}
else
{
prec->prossima = elenco;
}
prec = elenco;
i++;
}

  1. // Stampa
  2. elenco = start;
  3. while(elenco!=NULL)
  4. {
  5. printf(&quot;%s\n&quot;, elenco-&gt;titolo);
  6. printf(&quot;%s\n&quot;, elenco-&gt;autore);
  7. printf(&quot;%d\n&quot;, elenco-&gt;durata_in_sec);
  8. printf(&quot;%d\n&quot;, elenco-&gt;rips);
  9. elenco = elenco-&gt;prossima;
  10. }
  11. fclose(fp);
  12. // Free memory
  13. elenco = start;
  14. while (elenco != NULL) {
  15. struct elenco* temp = elenco;
  16. elenco = elenco-&gt;prossima;
  17. free(temp);
  18. }
  19. return 0;

}

  1. and this is the txt
  2. we will rock you
  3. queen
  4. 2:01
  5. it&#39;s my life
  6. bon jovi
  7. 3:46
  8. we will rock you
  9. queen
  10. 2:01
  11. the show must go on
  12. queen
  13. 4:36
  14. </details>
  15. # 答案1
  16. **得分**: 3
  17. 1. 使用符号常量代替魔法数字。
  18. 2. 更喜欢初始化变量。
  19. 3. 删除未使用的变量。 `i` 仅用于确定 `start` 是否已设置,因此可以将其删除。
  20. 4. 检查 `fopen()` 的返回值。
  21. 5. 使用 `str()` 宏让编译器生成最大字段宽度。
  22. 6. `" %[^\n]"` 通常比 `"%[^\n]%*c"` 更可读。前者忽略前导空格,而后者忽略最后一个字符。
  23. 7. `while(!feof())` 无法正常工作。在这种情况下,您可以使用单个 `fscanf()` 调用读取整个记录。这还可以让您在一个地方检查无效输入/`EOF`
  24. 8. 检查 `malloc()` 的返回值。
  25. 9. 随着每个记录的预分配,您需要释放上一个记录。
  26. 10. 确保您的字符串以 '\0' 结尾。
  27. 11. 在完成后立即使用 `fclose()` 关闭文件。
  28. 12. 限制变量的作用域。这会使您的代码更容易理解。
  29. 13. 更喜欢使用 `for` 循环进行迭代。
  30. 14. (未修复)考虑将代码拆分为较小的函数(`elenco_load()``elenco_print()``elenco_free()`)。这会使代码更容易理解和测试。
  31. 15. (未修复)考虑使用更具体的数据类型。您是否允许负的 `durata_in_sec`?您是否期望 `INT_MAX` 的持续时间,还是较小的数据类型足够?`secondi < 0 || secondi >= 60` 是否是有效输入(`unsigned char`)?
  32. 16. (未修复)由于您硬编码了 `rips=1`,考虑在 `struct elenco` 中将其替换为符号常量 `#define RIPS 1`。这样在打印时您只需执行 `print("%d\n", RIPS)`
  33. 请注意,这些是关于代码的建议和评论,而不是直接的翻译。
  34. <details>
  35. <summary>英文:</summary>
  36. 1. Use symbolic constants instead of magic numbers.
  37. 1. Prefer initialized variables.
  38. 1. Remove unused variables. `i` is only used to determine if `start` has been set so might as well eliminate it, too.
  39. 1. Check return value from `fopen()`.
  40. 1. Use the `str()` macro to let the compiler generate your maximum field width.
  41. 1. &quot; %[^\n]&quot; is usually more readable than &quot;%[^\n]%*c&quot;. The former ignores leading white space, while the latter ignores exactly one trailing character.
  42. 1. `while(!feof())` doesn&#39;t work. In this case you can read the whole record with a single `fscanf()` call. This also gives you one place to check for invalid input / `EOF`.
  43. 1. Check return value from `malloc()`.
  44. 1. As you pre-allocate each record you need to free the last one.
  45. 1. Ensure your strings are &#39;\0&#39; terminated.
  46. 1. `fclose()` file as soon as you are done.
  47. 1. Minimize scope of variables. This makes your code easier to reason about.
  48. 1. Prefer `for`-loops for iteration.
  49. 1. (Not fixed) Consider breaking your code into smaller functions (`elenco_load()`, `elenco_print()`, `elenco_free()`). It makes it easier to reason about and test.
  50. 1. (Not fixed) Consider using more specific types. Do you want to allow negative `durata_in_sec`? Do you expect duration of `INT_MAX` or would a smaller type do? Is `secondi &lt; 0 || secondi &gt;= 60` valid input (`unsigned char`)?
  51. 1. (Not fixed) As you hard-code `rips=1` consider eliminating it from `struct elenco` in favor of a symbolic constant `#define RIPS 1`. When printing you now just do `print(&quot;%d\n&quot;, RIPS).

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define TITOLO_LEN 29
#define AUTORE_LEN 29
#define str(s) str2(s)
#define str2(s) #s

struct elenco {
char titolo[TITOLO_LEN+1];
char autore[AUTORE_LEN+1];
int durata_in_sec;
int rips;
struct elenco *prossima;
};

int main() {
FILE *fp = fopen("musica.txt", "r");
if(!fp) {
printf("fopen failed\n");
return 1;
}
struct elenco *start = NULL;
for(struct elenco *prec = NULL;;) {
struct elenco *elenco = malloc(sizeof elenco);
if(!elenco) {
printf("malloc failed\n");
return 1;
}
int secondi, minuti;
int rv = fscanf(fp,
" %" str(TITOLO_LEN) "[^\n]"
" %" str(AUTORE_LEN) "[^\n]"
" %d:%d",
elenco->titolo,
elenco->autore,
&minuti,
&secondi
);
if(rv != 4) {
free(elenco);
if(prec)
prec->prossima = NULL;
break;
}
elenco->durata_in_sec = minuti
60+secondi;
elenco->rips=1;
if(!start)
start = elenco;
else
prec->prossima = elenco;
prec = elenco;
}
fclose(fp);

  1. // Stampa
  2. for(struct elenco *elenco = start; elenco; elenco = elenco-&gt;prossima) {
  3. printf(&quot;%s\n&quot;, elenco-&gt;titolo);
  4. printf(&quot;%s\n&quot;, elenco-&gt;autore);
  5. printf(&quot;%d\n&quot;, elenco-&gt;durata_in_sec);
  6. printf(&quot;%d\n&quot;, elenco-&gt;rips);
  7. }
  8. // Free memory
  9. for(struct elenco *elenco = start; elenco;) {
  10. struct elenco* temp = elenco;
  11. elenco = elenco-&gt;prossima;
  12. free(temp);
  13. }
  14. return 0;

}

  1. and example run:

we will rock you
queen
121
1
it's my life
bon jovi
226
1
we will rock you
queen
121
1
the show must go on
queen
276
1

  1. </details>

huangapple
  • 本文由 发表于 2023年6月9日 03:39:52
  • 转载请务必保留本文链接:https://go.coder-hub.com/76435205.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定