我将如何读取 C 中的文本文件?
How would I read a text file in C?
我有 file.txt
和
123456 2,00 beer
234567 2,50 milk
345678 3,30 ice cream
我想将此信息放入我的动态二维数组中:
char **dataBase;
dataBase = (char**)malloc(NUM_OF_PROD * sizeof(char*));
for(i = 0; i < NUM_OF_PROD; i++){
dataBase[i] = (char*)malloc(MAX_BUFFER* sizeof(char));
}
但我不知道怎么做。我们这里有 3 行。如果它是 C++,我会使用 getline()
但在这种情况下我找不到解决方案。
在您提到的评论中,您只关心实际读取文件。
以下是您读取文件的方式(目前未经测试,二进制模式):
#include <stdio.h>
int main()
{
FILE *file = fopen("path/to/your/file/yourfile.txt", "rb");
if(!file) return 1; //something went wrong!
long size = fseek(file, 0, SEEK_END);
char *buf = malloc(size);
fread(&buf, size, 1, file); //read all contents, once
fclose(file);
free(buf); //because this is just an example
return 0;
}
有关读取文件的更多信息,只需快速 google 搜索,您几乎可以找到所需的一切。
您可以使用 fgetc
和 realloc
实现您自己的 getline
版本。
#include <stdio.h>
#include <stdlib.h>
char *getline(FILE *file)
{
size_t size = 16; // Size of memory allocated for line
size_t len = 0; // Characters read
char *line = malloc(size);
// Return NULL if memory allocation fails
if (line == NULL)
return NULL;
for(;;) {
int c;
switch (c = fgetc(file)) {
// If End Of File is met, return the line up until this point
// if anything has been read
case EOF:
if (len == 0) {
free(line);
return NULL;
}
else {
line[len+1] = '[=10=]';
return line;
}
case '\n':
line[len+1] = '[=10=]'; // NUL terminate the string
return line;
default:
line[len++] = c;
}
// If the string plus NUL terminator is longer than size
// double the size of line
if (len + 1 >= size) {
size *= 2;
line = realloc(line, size);
// Return NULL if memory allocation fails
if (line == NULL)
return NULL;
}
}
}
还有很多 free/open 可以在网上找到相同功能的源代码实现。例如this GPL 2 one。如果您使用的是 POSIX 系统(例如 OS X 或 Linux),则在 stdio.h
.[=17 中已经找到了 getline
的版本=]
我通常对文件逐行使用 fgets() 函数(前提是它是文本文件)。
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#define LINELEN 200
#define NAMELEN 40
struct PRICELIST
{
char item[NAMELEN];
float price;
unsigned int order_no;
struct PRICELIST *next;
struct PRICELIST *prev;
};
void list_print_node (struct PRICELIST *node)
{
printf ("%d %4.2f %s\n", node->order_no, node->price, node->item);
}
void list_print (struct PRICELIST *head)
{
printf ("Order # Price Item\n");
printf ("------------------------------\n");
while (head)
{
list_print_node (head);
head = head->next;
}
}
void list_delete (struct PRICELIST *head)
{
if (head)
{
/* recursive call */
list_delete (head->next);
free (head);
}
}
struct PRICELIST *list_read (char *filename)
{
FILE *file;
char line[LINELEN];
struct PRICELIST *pricelist, *node, *prev;
char *p;
size_t len;
file = fopen (filename, "r");
if (file == NULL)
{
perror (filename);
return NULL;
}
pricelist = NULL;
prev = NULL;
while (1)
{
if (fgets (line, sizeof(line), file) == NULL)
break;
/* eat the newline at the end of the buffer, be CR/CRLF agnostic .. */
len = strlen (line) - 1;
if (line[len] == '\r' || line[len] == '\n')
{
line[len] = '[=10=]';
len --;
}
if (line[len] == '\r' || line[len] == '\n')
line[len] = '[=10=]';
/* allocate a new node in the list */
node = malloc (sizeof (struct PRICELIST));
if (node)
{
/* now use sscanf() for getting single elements */
sscanf (line, "%d %f", &node->order_no, &node->price);
/* since the item name might contain spaces this is not so easy .. */
p = line;
while (isspace(*p)) p++;
while (isdigit(*p)) p++;
while (isspace(*p)) p++;
while (isdigit(*p)) p++;
while (ispunct(*p)) p++;
while (isdigit(*p)) p++;
while (isspace(*p)) p++;
strncpy (node->item, p, sizeof(node->item));
node->next = NULL;
/* if this is the first node of the list assign the head to it */
if (pricelist == NULL)
pricelist = node;
/* append the new node to the end of the linked list */
if (prev)
prev->next = node;
node->prev = prev;
/* save it for the next entry */
prev = node;
}
}
/* we are done with the file, close it */
fclose (file);
return pricelist;
}
/* let's test it */
int main (int argc, char *argv[])
{
struct PRICELIST *pricelist;
if (argc < 2)
{
printf ("Usage: %s filename\n", argv[0]);
return 0;
}
pricelist = list_read (argv[1]);
if (pricelist)
{
/* print the list */
printf ("This is the price list (filename '%s'):\n\n", argv[1]);
list_print (pricelist);
/* delete the list */
list_delete (pricelist);
}
return 0;
}
我有 file.txt
和
123456 2,00 beer
234567 2,50 milk
345678 3,30 ice cream
我想将此信息放入我的动态二维数组中:
char **dataBase;
dataBase = (char**)malloc(NUM_OF_PROD * sizeof(char*));
for(i = 0; i < NUM_OF_PROD; i++){
dataBase[i] = (char*)malloc(MAX_BUFFER* sizeof(char));
}
但我不知道怎么做。我们这里有 3 行。如果它是 C++,我会使用 getline()
但在这种情况下我找不到解决方案。
在您提到的评论中,您只关心实际读取文件。 以下是您读取文件的方式(目前未经测试,二进制模式):
#include <stdio.h>
int main()
{
FILE *file = fopen("path/to/your/file/yourfile.txt", "rb");
if(!file) return 1; //something went wrong!
long size = fseek(file, 0, SEEK_END);
char *buf = malloc(size);
fread(&buf, size, 1, file); //read all contents, once
fclose(file);
free(buf); //because this is just an example
return 0;
}
有关读取文件的更多信息,只需快速 google 搜索,您几乎可以找到所需的一切。
您可以使用 fgetc
和 realloc
实现您自己的 getline
版本。
#include <stdio.h>
#include <stdlib.h>
char *getline(FILE *file)
{
size_t size = 16; // Size of memory allocated for line
size_t len = 0; // Characters read
char *line = malloc(size);
// Return NULL if memory allocation fails
if (line == NULL)
return NULL;
for(;;) {
int c;
switch (c = fgetc(file)) {
// If End Of File is met, return the line up until this point
// if anything has been read
case EOF:
if (len == 0) {
free(line);
return NULL;
}
else {
line[len+1] = '[=10=]';
return line;
}
case '\n':
line[len+1] = '[=10=]'; // NUL terminate the string
return line;
default:
line[len++] = c;
}
// If the string plus NUL terminator is longer than size
// double the size of line
if (len + 1 >= size) {
size *= 2;
line = realloc(line, size);
// Return NULL if memory allocation fails
if (line == NULL)
return NULL;
}
}
}
还有很多 free/open 可以在网上找到相同功能的源代码实现。例如this GPL 2 one。如果您使用的是 POSIX 系统(例如 OS X 或 Linux),则在 stdio.h
.[=17 中已经找到了 getline
的版本=]
我通常对文件逐行使用 fgets() 函数(前提是它是文本文件)。
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#define LINELEN 200
#define NAMELEN 40
struct PRICELIST
{
char item[NAMELEN];
float price;
unsigned int order_no;
struct PRICELIST *next;
struct PRICELIST *prev;
};
void list_print_node (struct PRICELIST *node)
{
printf ("%d %4.2f %s\n", node->order_no, node->price, node->item);
}
void list_print (struct PRICELIST *head)
{
printf ("Order # Price Item\n");
printf ("------------------------------\n");
while (head)
{
list_print_node (head);
head = head->next;
}
}
void list_delete (struct PRICELIST *head)
{
if (head)
{
/* recursive call */
list_delete (head->next);
free (head);
}
}
struct PRICELIST *list_read (char *filename)
{
FILE *file;
char line[LINELEN];
struct PRICELIST *pricelist, *node, *prev;
char *p;
size_t len;
file = fopen (filename, "r");
if (file == NULL)
{
perror (filename);
return NULL;
}
pricelist = NULL;
prev = NULL;
while (1)
{
if (fgets (line, sizeof(line), file) == NULL)
break;
/* eat the newline at the end of the buffer, be CR/CRLF agnostic .. */
len = strlen (line) - 1;
if (line[len] == '\r' || line[len] == '\n')
{
line[len] = '[=10=]';
len --;
}
if (line[len] == '\r' || line[len] == '\n')
line[len] = '[=10=]';
/* allocate a new node in the list */
node = malloc (sizeof (struct PRICELIST));
if (node)
{
/* now use sscanf() for getting single elements */
sscanf (line, "%d %f", &node->order_no, &node->price);
/* since the item name might contain spaces this is not so easy .. */
p = line;
while (isspace(*p)) p++;
while (isdigit(*p)) p++;
while (isspace(*p)) p++;
while (isdigit(*p)) p++;
while (ispunct(*p)) p++;
while (isdigit(*p)) p++;
while (isspace(*p)) p++;
strncpy (node->item, p, sizeof(node->item));
node->next = NULL;
/* if this is the first node of the list assign the head to it */
if (pricelist == NULL)
pricelist = node;
/* append the new node to the end of the linked list */
if (prev)
prev->next = node;
node->prev = prev;
/* save it for the next entry */
prev = node;
}
}
/* we are done with the file, close it */
fclose (file);
return pricelist;
}
/* let's test it */
int main (int argc, char *argv[])
{
struct PRICELIST *pricelist;
if (argc < 2)
{
printf ("Usage: %s filename\n", argv[0]);
return 0;
}
pricelist = list_read (argv[1]);
if (pricelist)
{
/* print the list */
printf ("This is the price list (filename '%s'):\n\n", argv[1]);
list_print (pricelist);
/* delete the list */
list_delete (pricelist);
}
return 0;
}