我在获得正确的输出方面遇到了问题,列表搞砸了。
1.我被告知在较小的部分打破我的while循环会有所帮助,但我似乎无法做到正确。 问题:打印时在某些列之间弹出一个数字“1”,在代码的下方用“-858993460”替换。 为什么会这样?
我的目标:“机器人”“Termintortyp”“idnr”\ n
AKA:“终结者”“T-800 / T-1000”“1-100”
2.我还想添加错误检查:
如果出现错误 - >打印错误消息,然后代码应继续,直到链表已用完。例如:11到12行之间它表示“FEL FEL FEL”或第16行“_____TERMINATOR T-1000 16”。如果在将txt.file读入链表时可以识别问题,并以某种方式替换“错误的终结者” - 带有错误信息的行可以解决我的问题,但我不知道如何正确地做到这一点。 有任何建议吗?
感谢我能得到的所有帮助!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Link {
char robot[12];
char terminatortyp[10];
int idnr;
struct Link *next;
};
typedef struct Link Link;
Link *first = NULL;
int main(void) {
int antal = 0;
Link a;
FILE *tsin = fopen("textfil1R.txt", "r");
if (tsin == NULL) {
printf("Kunde inte läsa filen 'textfil.txt'.\n");
exit(EXIT_FAILURE);
}
Link *temp;
while (fgets(a.robot, sizeof a.robot, tsin) != NULL)
{
temp = malloc(sizeof(Link));
strcpy(temp->robot, a.robot);
fgets(a.terminatortyp, sizeof a.terminatortyp, tsin);
strcpy(temp->terminatortyp, a.terminatortyp);
fscanf(tsin, "%d", &a.idnr);
temp->idnr = a.idnr;
temp->next = first;
first = temp;
++antal;
}
fclose(tsin);
Link *p = first;
while (p != NULL)
{
//printf("%d\n", p->idnr);
printf("%s", p->robot);
printf("%s", p->terminatortyp);
printf("%d\n", p->idnr);
p = p->next;
}
printf("%d", antal);
getch();
return 0;
}
我正在阅读的文本文件:
TERMINATOR T-800 1
TERMINATOR T-1000 2
TERMINATOR T-800 3
TERMINATOR T-800 4
TERMINATOR T-1000 5
TERMINATOR T-800 6
TERMINATOR T-800 7
TERMINATOR T-800 8
TERMINATOR T-1000 9
TERMINATOR T-800 10
TORMONUTTUR T-800 101
TERMINATOR T-800 11
FEL FEL FEL
TERMINATOR T-1000 12
TERMINATOR T-800 13
TERMINATOR T-800 14
TERMINATOR T-800 15
TERMINATOR T-1000 16
TERMINATOR T-800 17
TERMINATOR T-800 18
TERMINATOR T-1000 19
TERMINATOR T-800 20
TERMINATOR T-800 21
TERMINATOR T-800 22
TERMINATOR T-1000 23
TERMINATOR T-800 24
TERMINATOR T-800 25
TERMINATOR T-1000 26
TERMINATOR T-800 27
TERMINATOR T-800 28
TERMINATOR T-800 29
TERMINATOR T-1000 30
TERMINATOR T-800 31
TERMINATOR T-800 32
TERMINATOR T-1000 33
TERMINATOR T-800 34
TERMINATOR T-800 35
TERMINATOR T-800 36
TERMINATOR T-1000 37
TERMINATOR T-800 38
TERMINATOR T-800 39
TERMINATOR T-1000 40
TERMINATOR T-800 41
TERMINATOR T-800 42
TERMINATOR T-800 43
TERMINATOR T-1000 44
TERMINATOR T-800 45
TERMINATOR T-800 46
TERMINATOR T-1000 47
TERMINATOR T-800 48
TERMINATOR T-800 49
TERMINATOR T-800 50
TERMINATOR T-1000 51
TERMINATOR T-800 52
TERMINATOR T-800 53
TERMINATOR T-1000 54
TERMINATOR T-800 55
TERMINATOR T-800 56
TERMINATOR T-800 57
TERMINATOR T-1000 58
TERMINATOR T-800 59
TERMINATOR T-800 60
TERMINATOR T-1000 61
TERMINATOR T-800 62
TERMINATOR T-800 63
TERMINATOR T-800 64
TERMINATOR T-1000 65
TERMINATOR T-800 66
TERMINATOR T-800 67
TERMINATOR T-1000 68
TERMINATOR T-800 69
TERMINATOR T-800 70
TERMINATOR T-800 71
TERMINATOR T-1000 72
TERMINATOR T-800 73
TERMINATOR T-800 74
TERMINATOR T-1000 75
TERMINATOR T-800 76
TERMINATOR T-800 77
TERMINATOR T-800 78
TERMINATOR T-1000 79
TERMINATOR T-800 80
TERMINATOR T-800 81
TERMINATOR T-1000 82
TERMINATOR T-800 83
TERMINATOR T-1001 84
TERMINATOR T-800 85
TERMINATOR T-1000 86
TERMINATOR T-800 87
TERMINATOR T-800 88
TERMINATOR T-1000 89
TERMINATOR T-800 90
TERMINATOR T-800 91
TERMINATOR T-800 92
TERMINATOR T-1000 93
TERMINATOR T-850 94
TERMINATOR T-800 95
TERMINATOR T-1000 96
TERMINATOR T-800 97
TERMINATOR T-800 98
TERMINATOR T-800 99
TERMINATOR T-1000 100
答案 0 :(得分:1)
您正在使用fgets
,就好像它将在单个字符串中读取,直到下一个空格。然而,fgets
读取完整的行,直到它检测到换行符'\n'
或到达文件的末尾。
所以在声明fgets(a.robot, sizeof a.robot, tsin)
之后,a.robot
的值可能是TERMINATOR T-800 17\n
而不是TERMINATOR
。这一方面导致缓冲区溢出,并且循环中重复的fgets
语句实际上以完整的行读入当前的temp
对象。
while (fscanf(tsin, "%11s %9s %d", a.robot, a.terminatortyp, &a.idnr) == 3)
{
temp = malloc(sizeof(Link));
strcpy(temp->robot, a.robot);
strcpy(temp->terminatortyp, a.terminatortyp);
temp->idnr = a.idnr;
temp->next = first;
first = temp;
++antal;
}
请注意最大字段宽度说明符%11s
,以确保最多读入11个字符(+一个额外的字符串终止符),以便扫描适合大小为12的缓冲区。例如,cppreference/scanf:
%11s:如果使用宽度说明符,则匹配宽度或直到第一个 空白字符,以先出现者为准。始终存储空值 字符除了匹配的字符(所以参数数组 必须有至少宽度+ 1个字符的空间)
答案 1 :(得分:1)
使用fgets()
阅读行,而不是单词。
char line[100];
while (fgets(line, sizeof line, tsin) != NULL) {
现在解析这一行。使用%n
来保存扫描的偏移量 - 如果它到达那么远。请务必限制成员可接受的字符的最大宽度。可以进行额外的检查。这将帮助您入门。
struct Link entry = { 0 }; // zero fill members
int n = 0;
int lead;
sscanf(line," %n%11s%9s%d %n",&lead, entry.robot, entry.terminatortyp, &entry.idnr, &n);
// All specifiers scanned and no extra junk?
if (n == 0 || line[n]) {
printf("Bad line <%s>\n", line);
continue;
}
if (lead > 0) {
printf("leading spaces <%s>\n", line);
continue;
}
根据需要为成员添加健全性检查。
if (entry.idnr < 1 || entry.idnr > 9999) {
printf("Bad index <%s>\n", line);
continue;
}
成功,现在分配
struct Link *node = malloc(sizeof *node);
if (node == NULL) {
printf("Out of memory at line <%s>\n", line);
break;
}
*node = entry;
node->next = first;
first = node;
}
有什么建议吗?
@ imanoob,duärinteen noob