简体   繁体   English

结构中的 printf 字符数组也在 C 中打印下一个 int

[英]printf char array in structure also prints next int in C

I am very new to C and I don't know that much about it, although I do have some experience with programming as a whole.我对 C 非常陌生,我对此知之甚少,尽管我确实有一些编程方面的整体经验。 Whenever I get warnings or errors I just look it up online.每当我收到警告或错误时,我都会在网上查找。 But this one doesn't give a warning or an error.但是这个没有给出警告或错误。 It runs fine but it gives the wrong result.它运行良好,但给出了错误的结果。

So I have a structure with a char[16] and 2 ints:所以我有一个带有 char[16] 和 2 个整数的结构:

struct tile {
char layout[16];
int arrowClr;
int spPlacing;
};

I make an array of 200 of them with struct tile tiles[200];我用struct tile tiles[200];制作了一个由 200 个组成的数组struct tile tiles[200]; . . Then I open a file with a list of characters & numbers:然后我打开一个包含字符和数字列表的文件:

char resourceName[5];
scanf("%s",&*resourceName);

char rLoc[100];
sprintf(rLoc,"Resources/%s/",resourceName);

char tileLoc[100];
sprintf(tileLoc,"%sTiles.txt",rLoc);
FILE *tile_list;
tile_list = fopen(tileLoc,"r");

This is the list:这是清单:

   w s d   d   w20
wwwww   w s w  w10
w  wws ww  ww  w10
w  ww  ww sww  w10
   w  sw   w   w20
ws ww  ww  ww  w21
wwww     w  w  w10
ws  w   w   w   20
wwwww   w  sw   20
w  ww  dws dw  w10
wwww  s         20
w  ww sww  ww  w11
wwww   w s w   w20
wddw  sw   w   w10
wwww    s       20
w  wd swd  ww  w20
w  w  s     w  w20
wddww   w s w   20
wddww sww  ww  w20
w  ww  wws ww  w10
wwww   w   ww  w10

After that, I cycle through each line, storing the 16 first characters in the structure layout char (I used sprintf to make it know it was a character, because otherwise it just gave ascii value) and the last two numbers in the two ints:之后,我循环遍历每一行,在结构布局 char 中存储前 16 个字符(我使用 sprintf 使其知道它是一个字符,否则它只给出 ascii 值)和两个 int 中的最后两个数字:

for (int i=0;fgets(buf,100,tile_list)!=NULL;i++) {
strtok(buf,"\n");
//printf("%s",buf);
//printf("%c\n",buf[0]);
for (int e=0;e<16;e++) {
    sprintf(&tiles[i].layout[e],"%c",buf[e]);
}
tiles[i].arrowClr = buf[16];
tiles[i].spPlacing = buf[17];
}

Then, I display each of them to test it (without the two ints) with:然后,我显示它们中的每一个以测试它(没有两个整数):

for (int i=0;i<21;i++) {
printf("%s\n",tiles[i].layout);
}

And this is the result:这是结果:

   w s d   d   w2
wwwww   w s w  w1
w  wws ww  ww  w1
w  ww  ww sww  w1
   w  sw   w   w2
ws ww  ww  ww  w2
wwww     w  w  w1
ws  w   w   w   2
wwwww   w  sw   2
w  ww  dws dw  w1
wwww  s         2
w  ww sww  ww  w1
wwww   w s w   w2
wddw  sw   w   w1
wwww    s       2
w  wd swd  ww  w2
w  w  s     w  w2
wddww   w s w   2
wddww sww  ww  w2
w  ww  wws ww  w1
wwww   w   ww  w1

Removing the tiles[i].arrowClr = buf[16];移除tiles[i].arrowClr = buf[16]; makes that last number disappear from each line, and making the for loop before it go while e<15 instead of e<16 makes it disappear too, also making the last character before it vanish too.使最后一个数字从每一行消失,并在它之前进行 for 循环而e<15而不是e<16使它也消失,也使最后一个字符消失之前。

BTW I know tiles[i].arrowClr = buf[16];顺便说一句,我知道tiles[i].arrowClr = buf[16]; & tiles[i].spPlacing = buf[17]; & tiles[i].spPlacing = buf[17]; give me the ascii values of the numbers, that's just another problem, if anybody knows how to fix that too that would be useful给我数字的 ascii 值,这只是另一个问题,如果有人也知道如何解决这个问题,那会很有用

  1. You are not null terminating the layout string.您不是空终止布局字符串。 If this string is has 16 characters, add one to the layout array for the null.如果此字符串有 16 个字符,则向空值的布局数组添加一个。 layout[16] = '\\0'
  2. You need to convert ASCII strings to numbers if that is your intent.如果这是您的意图,您需要将 ASCII 字符串转换为数字。 arrowClr = buf[16] - '0';

In this line在这一行

printf("%s\n",tiles[i].layout);

there is expected to be a string terminator '\\0' at the end of the string.字符串末尾应该有一个字符串终止符'\\0' But you didn't put one.但是你没有放一个。 You built the string like this你像这样构建了字符串

for (int e=0;e<16;e++) {
    sprintf(&tiles[i].layout[e],"%c",buf[e]);
    ...

Your struct definition needs an extra char length您的结构定义需要额外的字符长度

char layout[17];        // <--- 16 to 17

and then after copying chars from the file, you need然后从文件复制字符后,你需要

tiles[i].layout[16] = '\0';

to terminate the string so you can print it.终止字符串,以便您可以打印它。

Then, the last two fields which you obtain with然后,您获得的最后两个字段

tiles[i].arrowClr = buf[16];
tiles[i].spPlacing = buf[17];

should be like this, to convert the single digit ASCII value to an int type应该是这样,将一位数的ASCII值转换为int类型

tiles[i].arrowClr = buf[16] - '0';
tiles[i].spPlacing = buf[17] - '0';

asuming that you intended the read value to be the number 1 or 2 and not the character '1' or '2' .假设您希望读取的值是数字12而不是字符'1''2'

As I and others mentioned, you need to allocate at least one more byte to your string.正如我和其他人提到的,您需要为您的字符串至少再分配一个字节。 But I would also recommend replacing your for loop (%c) with a simple call to snprintf() .但我也建议用对snprintf()的简单调用替换你的 for 循环 (%c snprintf() That will let you specify the 16 bytes you want from buf .这将允许您从buf指定您想要的 16 个字节。

You need a nul character ( '\\0' ) at the end of your string if you want to use it with standard C string functions.如果要将空字符 ( '\\0' ) 与标准 C 字符串函数一起使用,则字符串末尾需要一个空字符 ( '\\0' )。

Arrays in C don't have any length information associated with them, so in order for printf to know when it's reached the end of a string it needs some sort of marker. C 中的数组没有任何与它们相关的长度信息,因此为了让printf知道它何时到达字符串的末尾,它需要某种标记。 The nul character is used for this (also by all other string related functions like strlen , strcpy , etc.). nul 字符用于此(也由所有其他与字符串相关的函数,如strlenstrcpy等)。

You're using the layout field as an array of characters, but you're trying to print it as a string.您将layout字段用作字符数组,但您试图将其打印为字符串。 In C a string is a NULL terminated array of characters.在 C 中,字符串是以 NULL 结尾的字符数组。 Since your array doesn't have a NULL terminator, printf keeps looking until it finds a 0 byte, which it ends up finding in the arrowClr field which is laid out next in memory.由于您的数组没有 NULL 终止符, printf会继续查找,直到找到 0 字节,最终会在内存中的下一个arrowClr字段中找到该字节。 That's why it's printing out the number.这就是它打印出数字的原因。

You need to either make layout one character bigger, ie char layout[17] , and set layout[16] = 0 , or you would need to run printf in a loop to print each character individually.您需要使layout一个字符,即char layout[17] ,并设置layout[16] = 0 ,或者您需要在循环中运行printf以单独打印每个字符。 I'd recommend the former.我推荐前者。

To get the numerical values of the last two characters, you need to do this:要获取最后两个字符的数值,您需要这样做:

tiles[i].arrowClr = buf[16] - '0';
tiles[i].spPlacing = buf[17] - '0';

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM