在C中将字符附加到空字符串:

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

Appending Characters to an Empty String in C

问题

我对C语言相对较新,所以任何帮助理解正在发生的事情都将非常棒!

我有一个名为Token的结构体,定义如下:

  1. //Token结构体
  2. struct Token {
  3. char type[16];
  4. char value[1024];
  5. };

我试图从文件中读取字符,并将从文件中读取的字符附加到Token.value中,如下所示:

  1. struct Token newToken;
  2. char ch;
  3. ch = fgetc(file);
  4. strncat(newToken.value, &ch, 1);

这是有效的!

我的问题是,Token.value以我不理解的几个值开头,然后是我附加的字符。当我将newToken.value的结果打印到控制台时,我得到@�����TheCharactersIWantedToAppend。如果可能的话,我可以想办法事后删除或绕过这些字符,但如果不必要,我宁愿不这样做。

在分析字符时,我发现它们依次为索引1到5的字符:\330, \377, \377, \377, \177。我了解\377在C中是EOF的特殊字符,但在十进制中也是255。这些值是否构成内存地址?通过在strncat中使用&ch将地址添加到newToken.value中吗?如果是这样,如何防止它们进入newToken.value

注意: 如果我使用strncat(newToken.value, ch, 1)而不是strncat(newToken.value, &ch, 1)(ch与&ch),我会得到分段错误。

英文:

I'm relatively new to C, so any help understanding what's going on would be awesome!!!

I have a struct called Token that is as follows:

  1. //Token struct
  2. struct Token {
  3. char type[16];
  4. char value[1024];
  5. };

I am trying to read from a file and append characters read from the file into Token.value like so:

  1. struct Token newToken;
  2. char ch;
  3. ch = fgetc(file);
  4. strncat(newToken.value, &ch, 1);

THIS WORKS!

My problem is that Token.value begins with several values I don't understand, preceding the characters that I appended. When I print the result of newToken.value to the console, I get @�����TheCharactersIWantedToAppend. I could probably figure out a band-aid solution to retroactively remove or work around these characters, but I'd rather not if I don't have to.

In analyzing the � characters, I see them as (in order from index 1-5): \330, \377, \377, \377, \177. I read that \377 is a special character for EOF in C, but also 255 in decimal? Do these values make up a memory address? Am I adding the address to newToken.value by using &ch in strncat? If so, how can I keep them from getting into newToken.value?

Note: I get a segmentation fault if I use strncat(newToken.value, ch, 1) instead of strncat(newToken.value, &ch, 1) (ch vs. &ch).

答案1

得分: 2

以下是您要翻译的部分:

  1. I'll try to consolidate the answers already given in the comments.
  2. This version of the code uses `strncat()`, as yours, but solving the problems noted by Nick (we must initialize the target) and Dúthomhas (the second parameter to `strncat()` must be a string, and not a pointer to a single char) (Yes, a "string" is actually a `char[]` and the value passed to the function is a `char*`; but it must point to an array *of at least two chars*, the last one containing a `'
    I'll try to consolidate the answers already given in the comments.
  3. This version of the code uses `strncat()`, as yours, but solving the problems noted by Nick (we must initialize the target) and Dúthomhas (the second parameter to `strncat()` must be a string, and not a pointer to a single char) (Yes, a "string" is actually a `char[]` and the value passed to the function is a `char*`; but it must point to an array *of at least two chars*, the last one containing a `'\0'`.)
  4. Please be aware that `strncat()`, `strncpy()` and all related functions are tricky. They don't write more than N chars. But `strncpy()` only adds the final `'\0'` to the target string when the source has ***less*** than N chars; and `strncat()` ***always*** adds it, even if it the source has exactly N chars or more (edited; thanks, @Clifford).
  5. '`.)
  6. Please be aware that `strncat()`, `strncpy()` and all related functions are tricky. They don't write more than N chars. But `strncpy()` only adds the final `'
    I'll try to consolidate the answers already given in the comments.
  7. This version of the code uses `strncat()`, as yours, but solving the problems noted by Nick (we must initialize the target) and Dúthomhas (the second parameter to `strncat()` must be a string, and not a pointer to a single char) (Yes, a "string" is actually a `char[]` and the value passed to the function is a `char*`; but it must point to an array *of at least two chars*, the last one containing a `'\0'`.)
  8. Please be aware that `strncat()`, `strncpy()` and all related functions are tricky. They don't write more than N chars. But `strncpy()` only adds the final `'\0'` to the target string when the source has ***less*** than N chars; and `strncat()` ***always*** adds it, even if it the source has exactly N chars or more (edited; thanks, @Clifford).
  9. '` to the target string when the source has ***less*** than N chars; and `strncat()` ***always*** adds it, even if it the source has exactly N chars or more (edited; thanks, @Clifford).
  1. #include <stdio.h>
  2. #include <string.h>
  3. int main() {
  4. FILE* file = stdin; // fopen("test.txt", "r");
  5. if (file) {
  6. struct Token {
  7. char type[16];
  8. char value[1024];
  9. };
  10. struct Token newToken;
  11. newToken.value[0] = '\0'; // A '
    #include <stdio.h>
  12. #include <string.h>
  13. int main() {
  14.     FILE* file = stdin; // fopen("test.txt", "r");
  15.     if (file) {
  16.         struct Token {
  17.             char type[16];
  18.             char value[1024];
  19.         };
  20.         struct Token newToken;
  21.         newToken.value[0] = '\0';                       // A '\0' at the first position means "empty"
  22.         int aux;
  23.         char source[2] = "";                            // A literal "" has a single char with value '\0', but this syntax fills the entire array with '\0's
  24.         while ((aux = fgetc(file)) != EOF) {
  25.             source[0] = (char)aux;
  26.             strncat(newToken.value, source, 1);         // This appends AT MOST 1 CHAR (and always adds a final '\0')
  27.         }
  28.         strncat(newToken.value, "", 1);                 // As the source string is empty, it just adds a final '\0' (superfluous in this case)
  29.         printf(newToken.value);
  30.     }
  31.     return 0;
  32. }
  33. ' at the first position means "empty"
  34. int aux;
  35. char source[2] = ""; // A literal "" has a single char with value '
    #include <stdio.h>
  36. #include <string.h>
  37. int main() {
  38.     FILE* file = stdin; // fopen("test.txt", "r");
  39.     if (file) {
  40.         struct Token {
  41.             char type[16];
  42.             char value[1024];
  43.         };
  44.         struct Token newToken;
  45.         newToken.value[0] = '\0';                       // A '\0' at the first position means "empty"
  46.         int aux;
  47.         char source[2] = "";                            // A literal "" has a single char with value '\0', but this syntax fills the entire array with '\0's
  48.         while ((aux = fgetc(file)) != EOF) {
  49.             source[0] = (char)aux;
  50.             strncat(newToken.value, source, 1);         // This appends AT MOST 1 CHAR (and always adds a final '\0')
  51.         }
  52.         strncat(newToken.value, "", 1);                 // As the source string is empty, it just adds a final '\0' (superfluous in this case)
  53.         printf(newToken.value);
  54.     }
  55.     return 0;
  56. }
  57. ', but this syntax fills the entire array with '
    #include <stdio.h>
  58. #include <string.h>
  59. int main() {
  60.     FILE* file = stdin; // fopen("test.txt", "r");
  61.     if (file) {
  62.         struct Token {
  63.             char type[16];
  64.             char value[1024];
  65.         };
  66.         struct Token newToken;
  67.         newToken.value[0] = '\0';                       // A '\0' at the first position means "empty"
  68.         int aux;
  69.         char source[2] = "";                            // A literal "" has a single char with value '\0', but this syntax fills the entire array with '\0's
  70.         while ((aux = fgetc(file)) != EOF) {
  71.             source[0] = (char)aux;
  72.             strncat(newToken.value, source, 1);         // This appends AT MOST 1 CHAR (and always adds a final '\0')
  73.         }
  74.         strncat(newToken.value, "", 1);                 // As the source string is empty, it just adds a final '\0' (superfluous in this case)
  75.         printf(newToken.value);
  76.     }
  77.     return 0;
  78. }
  79. 's
  80. while ((aux = fgetc(file)) != EOF) {
  81. source[0] = (char)aux;
  82. strncat(newToken.value, source, 1); // This appends AT MOST 1 CHAR (and always adds a final '
    #include <stdio.h>
  83. #include <string.h>
  84. int main() {
  85.     FILE* file = stdin; // fopen("test.txt", "r");
  86.     if (file) {
  87.         struct Token {
  88.             char type[16];
  89.             char value[1024];
  90.         };
  91.         struct Token newToken;
  92.         newToken.value[0] = '\0';                       // A '\0' at the first position means "empty"
  93.         int aux;
  94.         char source[2] = "";                            // A literal "" has a single char with value '\0', but this syntax fills the entire array with '\0's
  95.         while ((aux = fgetc(file)) != EOF) {
  96.             source[0] = (char)aux;
  97.             strncat(newToken.value, source, 1);         // This appends AT MOST 1 CHAR (and always adds a final '\0')
  98.         }
  99.         strncat(newToken.value, "", 1);                 // As the source string is empty, it just adds a final '\0' (superfluous in this case)
  100.         printf(newToken.value);
  101.     }
  102.     return 0;
  103. }
  104. ')
  105. }
  106. strncat(newToken.value, "", 1); // As the source string is empty, it just adds a final '
    #include <stdio.h>
  107. #include <string.h>
  108. int main() {
  109.     FILE* file = stdin; // fopen("test.txt", "r");
  110.     if (file) {
  111.         struct Token {
  112.             char type[16];
  113.             char value[1024];
  114.         };
  115.         struct Token newToken;
  116.         newToken.value[0] = '\0';                       // A '\0' at the first position means "empty"
  117.         int aux;
  118.         char source[2] = "";                            // A literal "" has a single char with value '\0', but this syntax fills the entire array with '\0's
  119.         while ((aux = fgetc(file)) != EOF) {
  120.             source[0] = (char)aux;
  121.             strncat(newToken.value, source, 1);         // This appends AT MOST 1 CHAR (and always adds a final '\0')
  122.         }
  123.         strncat(newToken.value, "", 1);                 // As the source string is empty, it just adds a final '\0' (superfluous in this case)
  124.         printf(newToken.value);
  125.     }
  126.     return 0;
  127. }
  128. ' (superfluous in this case)
  129. printf(newToken.value);
  130. }
  131. return 0;
  132. }
  1. This other version uses an `index` variable and writes each singe char directly into the "current" position of the target string, without using `strncat()`. I think is simpler and more secure, because it doesn't mix the confusing semantics of single chars and strings.
  1. #include <stdio.h>
  2. #include <string.h>
  3. int main() {
  4. FILE* file = stdin; // fopen("test.txt", "r");
  5. if (file) {
  6. struct Token {
  7. int index = 0;
  8. char type[16];
  9. char value[1024]; // Max size is 1023 chars + '
    #include <stdio.h>
  10. #include <string.h>
  11. int main() {
  12.     FILE* file = stdin; // fopen("test.txt", "r");
  13.     if (file) {
  14.         struct Token {
  15.             int index = 0;
  16.             char type[16];
  17.             char value[1024];        // Max size is 1023 chars + '\0'
  18.         };
  19.         struct Token newToken;
  20.         newToken.value[0] = '\0';    // A '\0' at the first position means "empty". This is not really necessary anymore
  21.         int aux;
  22.         while ((aux = fgetc(file)) != EOF)
  23.             // Index will stop BEFORE 1024-1 (value[1022] will be the last "real" char, leaving space for a final '\0')
  24.             if (newToken.index < sizeof newToken.value -1)
  25.                 newToken.value[newToken.index++] = (char)aux;
  26.         newToken.value[newToken.index++] = '\0';
  27.         printf(newToken.value);
  28.     }
  29.     return 0;
  30. }
  31. '
  32. };
  33. struct Token newToken;
  34. newToken.value[0] = '\0'; // A '
    #include <stdio.h>
  35. #include <string.h>
  36. int main() {
  37.     FILE* file = stdin; // fopen("test.txt", "r");
  38.     if (file) {
  39.         struct Token {
  40.             int index = 0;
  41.             char type[16];
  42.             char value[1024];        // Max size is 1023 chars + '\0'
  43.         };
  44.         struct Token newToken;
  45.         newToken.value[0] = '\0';    // A '\0' at the first position means "empty". This is not really necessary anymore
  46.         int aux;
  47.         while ((aux = fgetc(file)) != EOF)
  48.             // Index will stop BEFORE 1024-1 (value[1022] will be the last "real" char, leaving space for a final '\0')
  49.             if (newToken.index < sizeof newToken.value -1)
  50.                 newToken.value[newToken.index++] = (char)aux;
  51.         newToken.value[newToken.index++] = '\0';
  52.         printf(newToken.value);
  53.     }
  54.     return 0;
  55. }
  56. ' at the first position means "empty". This is not really necessary anymore
  57. int aux;
  58. while ((aux = fgetc(file)) != EOF)
  59. // Index will stop BEFORE 1024-1 (value[1022] will be the last "real" char, leaving space for a final '
    #include <stdio.h>
  60. #include <string.h>
  61. int main() {
  62.     FILE* file = stdin; // fopen("test.txt", "r");
  63.     if (file) {
  64.         struct Token {
  65.             int index = 0;
  66.             char type[16];
  67.             char value[1024];        // Max size is 1023 chars + '\0'
  68.         };
  69.         struct Token newToken;
  70.         newToken.value[0] = '\0';    // A '\0' at the first position means "empty". This is not really necessary anymore
  71.         int aux;
  72.         while ((aux = fgetc(file)) != EOF)
  73.             // Index will stop BEFORE 1024-1 (value[1022] will be the last "real" char, leaving space for a final '\0')
  74.             if (newToken.index < sizeof newToken.value -1)
  75.                 newToken.value[newToken.index++] = (char)aux;
  76.         newToken.value[newToken.index++] = '\0';
  77.         printf(newToken.value);
  78.     }
  79.     return 0;
  80. }
  81. ')
  82. if (newToken.index < sizeof newToken.value -1)
  83. newToken.value[newToken.index++] = (char)aux;
  84. newToken.value[newToken.index++] = '\0';
  85. printf(newToken.value);
  86. }
  87. return 0;
  88. }

Edited: fgetc() returns an int and we should check for EOF before casting it to a char (thanks, @chqrlie).

  1. <details>
  2. <summary>英文:</summary>
  3. I&#39;ll try to consolidate the answers already given in the comments.
  4. This version of the code uses `strncat()`, as yours, but solving the problems noted by Nick (we must initialize the target) and D&#250;thomhas (the second parameter to `strncat()` must be a string, and not a pointer to a single char) (Yes, a &quot;string&quot; is actually a `char[]` and the value passed to the function is a `char*`; but it must point to an array *of at least two chars*, the last one containing a `&#39;
  5. <details>
  6. <summary>英文:</summary>
  7. I&#39;ll try to consolidate the answers already given in the comments.
  8. This version of the code uses `strncat()`, as yours, but solving the problems noted by Nick (we must initialize the target) and D&#250;thomhas (the second parameter to `strncat()` must be a string, and not a pointer to a single char) (Yes, a &quot;string&quot; is actually a `char[]` and the value passed to the function is a `char*`; but it must point to an array *of at least two chars*, the last one containing a `&#39;\0&#39;`.)
  9. Please be aware that `strncat()`, `strncpy()` and all related functions are tricky. They don&#39;t write more than N chars. But `strncpy()` only adds the final `&#39;\0&#39;` to the target string when the source has ***less*** than N chars; and `strncat()` ***always*** adds it, even if it the source has exactly N chars or more (edited; thanks, @Clifford).
  10. &#39;`.)
  11. Please be aware that `strncat()`, `strncpy()` and all related functions are tricky. They don&#39;t write more than N chars. But `strncpy()` only adds the final `&#39;
  12. <details>
  13. <summary>英文:</summary>
  14. I&#39;ll try to consolidate the answers already given in the comments.
  15. This version of the code uses `strncat()`, as yours, but solving the problems noted by Nick (we must initialize the target) and D&#250;thomhas (the second parameter to `strncat()` must be a string, and not a pointer to a single char) (Yes, a &quot;string&quot; is actually a `char[]` and the value passed to the function is a `char*`; but it must point to an array *of at least two chars*, the last one containing a `&#39;\0&#39;`.)
  16. Please be aware that `strncat()`, `strncpy()` and all related functions are tricky. They don&#39;t write more than N chars. But `strncpy()` only adds the final `&#39;\0&#39;` to the target string when the source has ***less*** than N chars; and `strncat()` ***always*** adds it, even if it the source has exactly N chars or more (edited; thanks, @Clifford).
  17. &#39;` to the target string when the source has ***less*** than N chars; and `strncat()` ***always*** adds it, even if it the source has exactly N chars or more (edited; thanks, @Clifford).

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

int main() {
FILE* file = stdin; // fopen("test.txt", "r");
if (file) {
struct Token {
char type[16];
char value[1024];
};

  1. struct Token newToken;
  2. newToken.value[0] = &#39;
        struct Token newToken;
  3. newToken.value[0] = &#39;\0&#39;;                       // A &#39;\0&#39; at the first position means &quot;empty&quot;
  4. int aux;
  5. char source[2] = &quot;&quot;;                            // A literal &quot;&quot; has a single char with value &#39;\0&#39;, but this syntax fills the entire array with &#39;\0&#39;s
  6. while ((aux = fgetc(file)) != EOF) {
  7. source[0] = (char)aux;
  8. strncat(newToken.value, source, 1);         // This appends AT MOST 1 CHAR (and always adds a final &#39;\0&#39;)
  9. }
  10. strncat(newToken.value, &quot;&quot;, 1);                 // As the source string is empty, it just adds a final &#39;\0&#39; (superfluous in this case)
  11. printf(newToken.value);
  12. }
  13. return 0;
  14. &#39;; // A &#39;
        struct Token newToken;
  15. newToken.value[0] = &#39;\0&#39;;                       // A &#39;\0&#39; at the first position means &quot;empty&quot;
  16. int aux;
  17. char source[2] = &quot;&quot;;                            // A literal &quot;&quot; has a single char with value &#39;\0&#39;, but this syntax fills the entire array with &#39;\0&#39;s
  18. while ((aux = fgetc(file)) != EOF) {
  19. source[0] = (char)aux;
  20. strncat(newToken.value, source, 1);         // This appends AT MOST 1 CHAR (and always adds a final &#39;\0&#39;)
  21. }
  22. strncat(newToken.value, &quot;&quot;, 1);                 // As the source string is empty, it just adds a final &#39;\0&#39; (superfluous in this case)
  23. printf(newToken.value);
  24. }
  25. return 0;
  26. &#39; at the first position means &quot;empty&quot;
  27. int aux;
  28. char source[2] = &quot;&quot;; // A literal &quot;&quot; has a single char with value &#39;
        struct Token newToken;
  29. newToken.value[0] = &#39;\0&#39;;                       // A &#39;\0&#39; at the first position means &quot;empty&quot;
  30. int aux;
  31. char source[2] = &quot;&quot;;                            // A literal &quot;&quot; has a single char with value &#39;\0&#39;, but this syntax fills the entire array with &#39;\0&#39;s
  32. while ((aux = fgetc(file)) != EOF) {
  33. source[0] = (char)aux;
  34. strncat(newToken.value, source, 1);         // This appends AT MOST 1 CHAR (and always adds a final &#39;\0&#39;)
  35. }
  36. strncat(newToken.value, &quot;&quot;, 1);                 // As the source string is empty, it just adds a final &#39;\0&#39; (superfluous in this case)
  37. printf(newToken.value);
  38. }
  39. return 0;
  40. &#39;, but this syntax fills the entire array with &#39;
        struct Token newToken;
  41. newToken.value[0] = &#39;\0&#39;;                       // A &#39;\0&#39; at the first position means &quot;empty&quot;
  42. int aux;
  43. char source[2] = &quot;&quot;;                            // A literal &quot;&quot; has a single char with value &#39;\0&#39;, but this syntax fills the entire array with &#39;\0&#39;s
  44. while ((aux = fgetc(file)) != EOF) {
  45. source[0] = (char)aux;
  46. strncat(newToken.value, source, 1);         // This appends AT MOST 1 CHAR (and always adds a final &#39;\0&#39;)
  47. }
  48. strncat(newToken.value, &quot;&quot;, 1);                 // As the source string is empty, it just adds a final &#39;\0&#39; (superfluous in this case)
  49. printf(newToken.value);
  50. }
  51. return 0;
  52. &#39;s
  53. while ((aux = fgetc(file)) != EOF) {
  54. source[0] = (char)aux;
  55. strncat(newToken.value, source, 1); // This appends AT MOST 1 CHAR (and always adds a final &#39;
        struct Token newToken;
  56. newToken.value[0] = &#39;\0&#39;;                       // A &#39;\0&#39; at the first position means &quot;empty&quot;
  57. int aux;
  58. char source[2] = &quot;&quot;;                            // A literal &quot;&quot; has a single char with value &#39;\0&#39;, but this syntax fills the entire array with &#39;\0&#39;s
  59. while ((aux = fgetc(file)) != EOF) {
  60. source[0] = (char)aux;
  61. strncat(newToken.value, source, 1);         // This appends AT MOST 1 CHAR (and always adds a final &#39;\0&#39;)
  62. }
  63. strncat(newToken.value, &quot;&quot;, 1);                 // As the source string is empty, it just adds a final &#39;\0&#39; (superfluous in this case)
  64. printf(newToken.value);
  65. }
  66. return 0;
  67. &#39;)
  68. }
  69. strncat(newToken.value, &quot;&quot;, 1); // As the source string is empty, it just adds a final &#39;
        struct Token newToken;
  70. newToken.value[0] = &#39;\0&#39;;                       // A &#39;\0&#39; at the first position means &quot;empty&quot;
  71. int aux;
  72. char source[2] = &quot;&quot;;                            // A literal &quot;&quot; has a single char with value &#39;\0&#39;, but this syntax fills the entire array with &#39;\0&#39;s
  73. while ((aux = fgetc(file)) != EOF) {
  74. source[0] = (char)aux;
  75. strncat(newToken.value, source, 1);         // This appends AT MOST 1 CHAR (and always adds a final &#39;\0&#39;)
  76. }
  77. strncat(newToken.value, &quot;&quot;, 1);                 // As the source string is empty, it just adds a final &#39;\0&#39; (superfluous in this case)
  78. printf(newToken.value);
  79. }
  80. return 0;
  81. &#39; (superfluous in this case)
  82. printf(newToken.value);
  83. }
  84. return 0;

}

  1. This other version uses an `index` variable and writes each singe char directly into the &quot;current&quot; position of the target string, without using `strncat()`. I think is simpler and more secure, because it doesn&#39;t mix the confusing semantics of single chars and strings.

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

int main() {
FILE* file = stdin; // fopen("test.txt", "r");
if (file) {
struct Token {
int index = 0;
char type[16];
char value[1024]; // Max size is 1023 chars + '\0'
};

  1. struct Token newToken;
  2. newToken.value[0] = &#39;
        struct Token newToken;
  3. newToken.value[0] = &#39;\0&#39;;    // A &#39;\0&#39; at the first position means &quot;empty&quot;. This is not really necessary anymore
  4. int aux;
  5. while ((aux = fgetc(file)) != EOF)
  6. // Index will stop BEFORE 1024-1 (value[1022] will be the last &quot;real&quot; char, leaving space for a final &#39;\0&#39;)
  7. if (newToken.index &lt; sizeof newToken.value -1)
  8. newToken.value[newToken.index++] = (char)aux;
  9. newToken.value[newToken.index++] = &#39;\0&#39;;
  10. printf(newToken.value);
  11. }
  12. return 0;
  13. &#39;; // A &#39;
        struct Token newToken;
  14. newToken.value[0] = &#39;\0&#39;;    // A &#39;\0&#39; at the first position means &quot;empty&quot;. This is not really necessary anymore
  15. int aux;
  16. while ((aux = fgetc(file)) != EOF)
  17. // Index will stop BEFORE 1024-1 (value[1022] will be the last &quot;real&quot; char, leaving space for a final &#39;\0&#39;)
  18. if (newToken.index &lt; sizeof newToken.value -1)
  19. newToken.value[newToken.index++] = (char)aux;
  20. newToken.value[newToken.index++] = &#39;\0&#39;;
  21. printf(newToken.value);
  22. }
  23. return 0;
  24. &#39; at the first position means &quot;empty&quot;. This is not really necessary anymore
  25. int aux;
  26. while ((aux = fgetc(file)) != EOF)
  27. // Index will stop BEFORE 1024-1 (value[1022] will be the last &quot;real&quot; char, leaving space for a final &#39;
        struct Token newToken;
  28. newToken.value[0] = &#39;\0&#39;;    // A &#39;\0&#39; at the first position means &quot;empty&quot;. This is not really necessary anymore
  29. int aux;
  30. while ((aux = fgetc(file)) != EOF)
  31. // Index will stop BEFORE 1024-1 (value[1022] will be the last &quot;real&quot; char, leaving space for a final &#39;\0&#39;)
  32. if (newToken.index &lt; sizeof newToken.value -1)
  33. newToken.value[newToken.index++] = (char)aux;
  34. newToken.value[newToken.index++] = &#39;\0&#39;;
  35. printf(newToken.value);
  36. }
  37. return 0;
  38. &#39;)
  39. if (newToken.index &lt; sizeof newToken.value -1)
  40. newToken.value[newToken.index++] = (char)aux;
  41. newToken.value[newToken.index++] = &#39;
        struct Token newToken;
  42. newToken.value[0] = &#39;\0&#39;;    // A &#39;\0&#39; at the first position means &quot;empty&quot;. This is not really necessary anymore
  43. int aux;
  44. while ((aux = fgetc(file)) != EOF)
  45. // Index will stop BEFORE 1024-1 (value[1022] will be the last &quot;real&quot; char, leaving space for a final &#39;\0&#39;)
  46. if (newToken.index &lt; sizeof newToken.value -1)
  47. newToken.value[newToken.index++] = (char)aux;
  48. newToken.value[newToken.index++] = &#39;\0&#39;;
  49. printf(newToken.value);
  50. }
  51. return 0;
  52. &#39;;
  53. printf(newToken.value);
  54. }
  55. return 0;

}

  1. **Edited**: `fgetc()` returns an `int` and we should check for EOF *before* casting it to a `char` (thanks, @chqrlie).
  2. </details>
  3. # 答案2
  4. **得分**: 1
  5. 以下是翻译的内容:
  6. 你正在附加未初始化的字符串,因此可能包含_任何内容_。字符串的结束由NUL(0)字符表示,在你的示例中,在6个字节后恰好有一个,但`value`数组中可能没有任何字符,因此代码存在严重缺陷,会导致不确定的行为。
  7. 你需要将`newToken`实例初始化为空字符串。例如:
  8. ```C
  9. struct Token newToken = { "", "" };

或者初始化整个结构为零:

  1. struct Token newToken = { 0 };

关键是,C语言不会初始化非静态对象,除非有明确的初始值。

此外,使用strncat()非常低效,具有取决于目标字符串长度的不确定执行时间(请参考https://www.joelonsoftware.com/2001/12/11/back-to-basics/)。

在这种情况下,你最好维护已添加的字符数,并直接将字符和终止符写入数组。例如:

  1. size_t index;
  2. int ch = 0;
  3. do
  4. {
  5. ch = fgetc(file);
  6. if (ch != EOF)
  7. {
  8. newToken.value[index] = (char)ch;
  9. index++;
  10. newToken.value[index] = '
    size_t index;
  11. int ch = 0;
  12. do
  13. {
  14.     ch = fgetc(file);
  15.     if (ch != EOF)
  16.     {
  17.         newToken.value[index] = (char)ch;
  18.         index++;
  19.         newToken.value[index] = '\0';
  20.     }
  21. } while (ch != EOF &&
  22.          index < sizeof(newToken.value) - 1);
  23. ';
  24. }
  25. } while (ch != EOF &&
  26. index < sizeof(newToken.value) - 1);
英文:

You are appending string that is not initialised, so can contain anything. The end I'd a string is indicated by a NUL(0) character, and in your example there happened to be one after 6 bytes, but there need not be any within the value array, so the code is seriously flawed, and will result in non-deterministic behaviour.

You need to initialise the newToken instance to empty string. For example:

  1. struct Token newToken = { &quot;&quot;, &quot;&quot; } ;

or to zero initialise the whole structure:

  1. struct Token newToken = { 0 } ;

The point is that C does not initialise non-static objects without an explicit initialiser.

Furthermore using strncat() is very inefficient and has non-deterministic execution time that depends on the length of the destination string (see https://www.joelonsoftware.com/2001/12/11/back-to-basics/).

In this case you would do better to maintain a count of the number of characters added, and write the character and terminator directly to the array. For example:

  1. size_t index ;
  2. int ch = 0 ;
  3. do
  4. {
  5. ch = fgetc(file);
  6. if( ch != EOF )
  7. {
  8. newToken.value[index] = (char)ch ;
  9. index++ ;
  10. newToken.value[index] = &#39;\0&#39; ;
  11. }
  12. } while( ch != EOF &amp;&amp;
  13. index &lt; size of(newToken.value) - 1 ) ;

huangapple
  • 本文由 发表于 2023年2月16日 10:52:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/75467376.html
匿名

发表评论

匿名网友

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

确定