如何在c中按行或列拆分文件
我试图将文件中的一行分割成由一个空格分隔的不同部分,但它不起作用。。。所以我的问题是:我如何将我的行分割成不同的部分,并对文件的每一行进行分割,然后将这些部分放入动态分配的向量/矩阵中?或者也可以按列。告诉我你认为合适的 该文件如下所示:如何在c中按行或列拆分文件,c,C,我试图将文件中的一行分割成由一个空格分隔的不同部分,但它不起作用。。。所以我的问题是:我如何将我的行分割成不同的部分,并对文件的每一行进行分割,然后将这些部分放入动态分配的向量/矩阵中?或者也可以按列。告诉我你认为合适的 该文件如下所示: BERLIN CAR 1 U BERLIN CAR 1 R BUCHAREST JACKET 2 D NEW_YORK DOLL 7 U BERLIN ROBOT 5 L BUCHAREST BALL 4 L 我想这样做。 例如: 到
BERLIN CAR 1 U
BERLIN CAR 1 R
BUCHAREST JACKET 2 D
NEW_YORK DOLL 7 U
BERLIN ROBOT 5 L
BUCHAREST BALL 4 L
我想这样做。
例如:
到目前为止我的代码(最大字符串长度定义为30):
inti;
字符*p,**a,delim[]=”;
a=malloc(100*sizeof(char));
对于(i=0;i<100;i++)
{
a[i]=calloc(最大字符串长度,sizeof(char));
}
而(!feof(stdin))
{
fgets(*a,500,标准DIN);
p=strtok(*a,delim);
}
strtok
是正确的函数,但您使用的是错误的
曼斯特克
strtok()
函数将字符串分解为零个或多个非空令牌序列。
在第一次调用strtok()
时,应指定要分析的字符串
在str
中。在应该解析相同字符串的每个后续调用中,str
必须为NULL
我把引文中最重要的部分加粗了
还要记住,如果需要源代码,strtok会修改源代码
之后,你必须复印一份
// assuming that line is either a char[] or char*
char *token = strtok(line, " ");
if(token == NULL)
{
// error detection
}
while(token = strtok(NULL, " "))
{
// do the work
}
另外,我建议不要在中使用sizeof()
malloc
/calloc
/realloc
调用。很容易忽略一个*
,而使
错误。更好:
int *myarray = malloc(size * sizeof *myarray);
// or
int *mayarray = calloc(size, sizeof *myarray);
使用sizeof*var
更好,因为它总是返回正确的大小
最后一件事:
while(!feof(stdin))
看
更好
char buffer[1024];
while(fgets(buffer, sizeof buffer, stdin))
{
// do the work here
}
编辑
这里有一个使用strtok
的示例实现。我的实现使用
MAP
s的数组。看看我构造/销毁MAP
对象的方式,以及内存是如何分配的。显然,这可以用更少的代码和更少的strdup来实现,但我认为这更准确地说明了如何使用这些函数。您可以将此代码用作基础,也可以将其用作基本想法
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
typedef struct{
char *destination;
char *type_present;
int no_available_presents;
char *direction;
} MAP;
MAP *create_map(const char *dest, const char *type, int present, const char *dir);
void free_map(MAP *map);
void print_map(MAP *map);
MAP *create_map(const char *dest, const char *type, int present, const char *dir)
{
MAP *map = calloc(1, sizeof *map);
if(map == NULL)
return NULL;
int errors = 0;
if(!(map->destination = strdup(dest)))
errors++;
if(!(map->type_present = strdup(type)))
errors++;
if(!(map->direction = strdup(dir)))
errors++;
map->no_available_presents = present;
if(!errors)
return map;
free_map(map);
return NULL;
}
void free_map(MAP *map)
{
if(map == NULL)
return;
free(map->destination);
free(map->type_present);
free(map->direction);
free(map);
}
void print_map(MAP *map)
{
if(map == NULL)
{
puts("(null)");
return;
}
printf("destination: %s\n", map->destination);
printf("type: %s\n", map->type_present);
printf("present: %d\n", map->no_available_presents);
printf("direction: %s\n", map->direction);
}
int main(char argc, char **argv)
{
FILE *fp;
if(argc != 1 && argc != 2)
{
fprintf(stderr, "usage: %s [database]\n", argv[0]);
return 1;
}
if(argc == 1)
fp = stdin;
else
fp = fopen(argv[1], "r");
if(fp == NULL)
{
fprintf(stderr, "Could not open '%s': %s\n", argv[1], strerror(errno));
return 1;
}
MAP **maps = NULL;
size_t map_len = 0;
char line[1024];
const char *delim = " \r\n";
while(fgets(line, sizeof line, fp))
{
int pres;
char *dest = NULL, *type = NULL, *dir = NULL, *token;
token = strtok(line, delim);
dest = strdup(token);
token = strtok(NULL, delim);
type = strdup(token);
token = strtok(NULL, delim);
pres = atoi(token);
token = strtok(NULL, delim);
dir = strdup(token);
if(dest == NULL || type == NULL || dir == NULL)
{
// ignore line
free(dest);free(type);free(dir);
continue;
}
MAP *new_map = create_map(dest, type, pres, dir);
if(new_map == NULL)
{
// ignore line
free(dest);free(type);free(dir);
continue;
}
MAP **tmp_map = realloc(maps, (map_len + 1) * sizeof *tmp_map);
if(tmp_map == NULL)
{
// ignore line
free_map(new_map);
free(dest);free(type);free(dir);
continue;
}
maps = tmp_map;
maps[map_len++] = new_map;
free(dest);free(type);free(dir);
}
for(int i = 0; i < map_len; ++i)
{
print_map(maps[i]);
puts("---");
free_map(maps[i]);
}
free(maps);
if(fp != stdin)
fclose(fp);
return 0;
}
while(!feof(stdin)){fgets(*a,500,stdin);
:所以最后一行被标记了两次@Jean-Françoisfare将链接放到著名的why iswhile(!feof())
总是错误的。我认为a=malloc(100*sizeof(char));
的可能重复应该是a=malloc(100*sizeof(char*));
@BenjaminJ.-第一个分配应该是指向每一行的指针,因此它可能是a=malloc(100*sizeof(char*));; 59440irst标记。读取函数fgets
保留输入字符串中的任何换行符。在strtok
的上下文中,它将通过在定界符字符串中包含换行符来去除该标记,例如strtok(..,“\n\r”)
@WeatherVane这是个好建议,我从来没有想过要这么做。我通常在做其他事情之前先把\n
去掉。
char buffer[1024];
while(fgets(buffer, sizeof buffer, stdin))
{
// do the work here
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
typedef struct{
char *destination;
char *type_present;
int no_available_presents;
char *direction;
} MAP;
MAP *create_map(const char *dest, const char *type, int present, const char *dir);
void free_map(MAP *map);
void print_map(MAP *map);
MAP *create_map(const char *dest, const char *type, int present, const char *dir)
{
MAP *map = calloc(1, sizeof *map);
if(map == NULL)
return NULL;
int errors = 0;
if(!(map->destination = strdup(dest)))
errors++;
if(!(map->type_present = strdup(type)))
errors++;
if(!(map->direction = strdup(dir)))
errors++;
map->no_available_presents = present;
if(!errors)
return map;
free_map(map);
return NULL;
}
void free_map(MAP *map)
{
if(map == NULL)
return;
free(map->destination);
free(map->type_present);
free(map->direction);
free(map);
}
void print_map(MAP *map)
{
if(map == NULL)
{
puts("(null)");
return;
}
printf("destination: %s\n", map->destination);
printf("type: %s\n", map->type_present);
printf("present: %d\n", map->no_available_presents);
printf("direction: %s\n", map->direction);
}
int main(char argc, char **argv)
{
FILE *fp;
if(argc != 1 && argc != 2)
{
fprintf(stderr, "usage: %s [database]\n", argv[0]);
return 1;
}
if(argc == 1)
fp = stdin;
else
fp = fopen(argv[1], "r");
if(fp == NULL)
{
fprintf(stderr, "Could not open '%s': %s\n", argv[1], strerror(errno));
return 1;
}
MAP **maps = NULL;
size_t map_len = 0;
char line[1024];
const char *delim = " \r\n";
while(fgets(line, sizeof line, fp))
{
int pres;
char *dest = NULL, *type = NULL, *dir = NULL, *token;
token = strtok(line, delim);
dest = strdup(token);
token = strtok(NULL, delim);
type = strdup(token);
token = strtok(NULL, delim);
pres = atoi(token);
token = strtok(NULL, delim);
dir = strdup(token);
if(dest == NULL || type == NULL || dir == NULL)
{
// ignore line
free(dest);free(type);free(dir);
continue;
}
MAP *new_map = create_map(dest, type, pres, dir);
if(new_map == NULL)
{
// ignore line
free(dest);free(type);free(dir);
continue;
}
MAP **tmp_map = realloc(maps, (map_len + 1) * sizeof *tmp_map);
if(tmp_map == NULL)
{
// ignore line
free_map(new_map);
free(dest);free(type);free(dir);
continue;
}
maps = tmp_map;
maps[map_len++] = new_map;
free(dest);free(type);free(dir);
}
for(int i = 0; i < map_len; ++i)
{
print_map(maps[i]);
puts("---");
free_map(maps[i]);
}
free(maps);
if(fp != stdin)
fclose(fp);
return 0;
}
destination: BERLIN
type: CAR
present: 1
direction: U
---
destination: BERLIN
type: CAR
present: 1
direction: R
---
destination: BUCHAREST
type: JACKET
present: 2
direction: D
---
destination: NEW_YORK
type: DOLL
present: 7
direction: U
---
destination: BERLIN
type: ROBOT
present: 5
direction: L
---
destination: BUCHAREST
type: BALL
present: 4
direction: L
---