我遇到make[]
数组的输出问题。所以首先我将名为Carss.txt
的文件标记,只抓取第三个&第五列,并将结果分别存储在make[]
数组和year[]
数组中。
我测试了make[]
数组,看它是否会输出我想要的结果。它在while(fgets)
循环内部进行,但是当我在while(fgets)
的外部进行测试时,它正在重复。
我不明白这是什么问题。我的程序和文本文件在下面提供。
在while(fgets)
循环中输出make数组:(我想要的)
FORD
FORD
JAYCO
在while(fgets)
循环之外输出make数组:(不是我想要的)
JAYCO
JAYCO
JAYCO
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main() {
FILE * fp;
char * filename = "Carss.txt";
char lines[100000], blank[100000];
char * token, * del = " ";
int i = 0, c, d = 0, j;
char * make[10000];
char * year[10000];
if ((fp = fopen(filename, "r")) == NULL) /* Opens the file */ {
printf("can't open %s\n", filename);
exit(1);
}
c = 0;
while (fgets(lines, sizeof(lines), fp) != NULL) {
token = strtok(lines, "\t");
i = 1;
while (i < 5) {
token = strtok(NULL, "\t");
if (i == 2) {
make[c] = token;
}
if (i == 4) {
year[c] = token;
}
i++;
}
printf("%s\n", make[c]); /* OUTPUT OF THE ARRAY HERE IS WHAT I WANTED */
c++;
}
c = 0;
while (c < 3) {
printf("%d\n", c);
printf("%s\n", make[c]);
c++;
}
}
我标记的文本文件:Carss.txt
1 02V288000 FORD FOCUS 2001 02S41 ELECTRICAL SYSTEM:BATTERY:CABLES FORD MOTOR COMPANY 19990719 20010531 V 291854 20030210 ODI Ford Motor Company 20021106 20021106 CERTAIN PASSENGER VEHICLES EQUIPPED WITH ZETEC ENGINES, LOOSE OR BROKEN ATTACHMENTS AND MISROUTED BATTERY CABLES COULD LEAD TO CABLE INSULATION DAMAGE. THIS, IN TURN, COULD CAUSE THE BATTERY CABLES TO SHORT RESULTING IN HEAT DAMAGE TO THE CABLES. BESIDES HEAT DAMAGE, THE "CHECK ENGINE" LIGHT MAY ILLUMINATE, THE VEHICLE MAY FAIL TO START, OR SMOKE, MELTING, OR FIRE COULD ALSO OCCUR. DEALERS WILL INSPECT THE BATTERY CABLES FOR THE CONDITION OF THE CABLE INSULATION AND PROPER TIGHTENING OF THE TERMINAL ENDS. AS NECESSARY, CABLES WILL BE REROUTED, RETAINING CLIPS INSTALLED, AND DAMAGED BATTERY CABLES REPLACED. OWNER NOTIFICATION BEGAN FEBRUARY 10, 2003. OWNERS WHO DO NOT RECEIVE THE FREE REMEDY WITHIN A REASONABLE TIME SHOULD CONTACT FORD AT 1-866-436-7332. ALSO CONTACT THE NATIONAL HIGHWAY TRAFFIC SAFETY ADMINISTRATION'S AUTO SAFETY HOTLINE AT 1-888-DASH-2-DOT (1-888-327-4236). 000015339000215022000000202
2 02V288000 FORD FOCUS 2000 02S41 ELECTRICAL SYSTEM:BATTERY:CABLES FORD MOTOR COMPANY 19990719 20010531 V 291854 20030210 ODI Ford Motor Company 20021106 20021106 CERTAIN PASSENGER VEHICLES EQUIPPED WITH ZETEC ENGINES, LOOSE OR BROKEN ATTACHMENTS AND MISROUTED BATTERY CABLES COULD LEAD TO CABLE INSULATION DAMAGE. THIS, IN TURN, COULD CAUSE THE BATTERY CABLES TO SHORT RESULTING IN HEAT DAMAGE TO THE CABLES. BESIDES HEAT DAMAGE, THE "CHECK ENGINE" LIGHT MAY ILLUMINATE, THE VEHICLE MAY FAIL TO START, OR SMOKE, MELTING, OR FIRE COULD ALSO OCCUR. DEALERS WILL INSPECT THE BATTERY CABLES FOR THE CONDITION OF THE CABLE INSULATION AND PROPER TIGHTENING OF THE TERMINAL ENDS. AS NECESSARY, CABLES WILL BE REROUTED, RETAINING CLIPS INSTALLED, AND DAMAGED BATTERY CABLES REPLACED. OWNER NOTIFICATION BEGAN FEBRUARY 10, 2003. OWNERS WHO DO NOT RECEIVE THE FREE REMEDY WITHIN A REASONABLE TIME SHOULD CONTACT FORD AT 1-866-436-7332. ALSO CONTACT THE NATIONAL HIGHWAY TRAFFIC SAFETY ADMINISTRATION'S AUTO SAFETY HOTLINE AT 1-888-DASH-2-DOT (1-888-327-4236). 000015339000215021000000202
3 02V236000 JAYCO FT EAGLE 10 SG 2003 EQUIPMENT:OTHER:LABELS JAYCO, INC. 20020730 20020813 V 86 20020923 MFR Jayco, Inc. 20020904 20020912 ON CERTAIN FOLDING TENT CAMPERS, THE FEDERAL CERTIFICATION (AND RVIA) LABELS HAVE THE INCORRECT GROSS VEHICLE WEIGHT RATING, TIRE SIZE, AND INFLATION PRESSURE LISTED. IF THE TIRES WERE INFLATED TO 80 PSI, THEY COULD BLOW RESULTING IN A POSSIBLE CRASH. OWNERS WILL BE MAILED CORRECT LABELS FOR INSTALLATION ON THEIR VEHICLES. OWNER NOTIFICATION BEGAN SEPTEMBER 23, 2002. OWNERS SHOULD CONTACT JAYCO AT 1-877-825-4782. ALSO, CUSTOMERS CAN CONTACT THE NATIONAL HIGHWAY TRAFFIC SAFETY ADMINISTRATION'S AUTO SAFETY HOTLINE AT 1-888-DASH-2-DOT (1-888-327-4236). 000015210000106403000000349
答案 0 :(得分:4)
执行此操作时:
token = strtok(NULL, "\t");
if(i==2)
{
make[c] = token;
}
您不接受字符串的副本,只接受指针的引用。然后,下次调用fgets
时,字符串将被覆盖,并且所有引用都指向新字符串。所以,当你到达程序结束时,所有指针都指向写入该内存的 last 事物。
试试这个:
make[c] = strdup(token);
这将分配新内存,复制字符串,并返回新指针。副本不会被覆盖。 strdup
在内部调用malloc
,所以当你完成记忆时你应该free
。
答案 1 :(得分:1)
在循环内,make[c] = token
在char lines[]
内记录一个地址。由于在下一次迭代时会覆盖该缓冲区,因此您需要将令牌复制到其他位置以保证其安全。
只需使用make[c] = strdup(token)
(以及年份相同)即可 - 但请记住,在任何真实的程序中,当您完成它们时,您现在应该free
所有的make和year字符串。
答案 2 :(得分:0)
您使用错误的数据结构来存储结果。
make
数组是一个指针数组。这意味着您存储的所有内容都有一个内存地址,在您的情况下,是strtok
操作期间使用的指针的内存地址。这不是你想要的,因为你不知道之后那个记忆会发生什么;在这种情况下,似乎在每次连续调用函数时都会被覆盖。
您需要使用多维数组或使用malloc()
或strdup()
来创建char *
返回的strtok()
值的副本。
答案 3 :(得分:0)
strtok在静态缓冲区上运行
当你写
strtok(lines, "\t");
lines
缓冲区被复制到内部静态缓冲区 - 而strtok只有一个静态缓冲区 - 所以每次你的while循环迭代时,新内容被放置在静态缓冲区中,使任何先前的指针无效,即make []和年[]。
为了保留令牌,你需要为它们分配单独的内存,这些内存在循环结束时不会被破坏。这可以通过几种方式完成,比如在其他海报上提到的每个字符串上使用strdup,尽管会有大量的簿记然后释放meory。您还可以使用其他数据结构,例如一个链表来存储值而不是有很多指针:
typedef struct record
{
char make[32]; // lets say the max length of make is 32
char year[10];
struct record* next;
} record;
每当您从文件中读取新行时,都会创建一条新记录:
record* first = NULL;
record* last = NULL;
while (fgets(lines, sizeof(lines), fp) != NULL)
{
// first create the record
record* newRecord = malloc(sizeof(record));
newRecord->next = NULL;
// parse the line
int column = 0;
for (char* token = strtok(lines,"\t"); token != NULL; token = strtok(NULL, "\t"), ++column)
{
switch(column)
{
case 2:
strncpy(newRecord->make, token, sizeof(newRecord.make));
break;
case 4:
strncpy(newRecord->year, token, sizeof(newRecord.year));
break;
default: // ignore
break;
}
}
// put in the list
if (first == NULL)
{
first = last = newRecord;
}
else
{
last->next = newRecord;
last = newRecord;
}
}
现在你有一个列表中你感兴趣的部分。你可以用
打印出列表for (record* rec = first; rec != NULL; rec = rec->next)
{
printf( "%s, %s\n", rec->make, rec->year );
}
//免责声明,尚未编译此内容。