无法从文件打印字符串
Having trouble printing string from a file
我的任务是从文件中读取单词并分别打印每个单词。
到目前为止我得到了这个:
#define MAX 100000
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct node *ptr;
typedef struct node {
char *data;
ptr next;
} node;
ptr head = NULL;
void add(char *data) {
node *new_node = malloc(sizeof(node));
new_node->data = data;
new_node->next = head;
head = new_node;
printf("Adding new word:%s\n",data);
}
void print_list() {
node *current = head;
while (current != NULL) {
printf("%s\n", current->data);
current = current->next;
}
}
void free_list(ptr *hnode)
{
ptr p;
while(*hnode){
p = *hnode;
*hnode = (*hnode)->next;
free(p);
}
}
int main(int argc, char *argv[]) {
FILE *file;
char buffer[MAX];
char ch;
int i = 0;
if (argc != 2) {
printf("Usage: %s <file>\n", argv[0]);
exit(EXIT_FAILURE);
}
file = fopen(argv[1], "r");
if (file == NULL) {
printf("Error opening file\n");
exit(EXIT_FAILURE);
}
while(i < MAX-1 && !feof(file))
{
if((ch = fgetc(file)) == ' '|| ch == '\n')
{
buffer[i] = '[=10=]';
add(buffer);
i = 0;
}
else{
if(ch == EOF)
break;
buffer[i++] = ch;
}
}
print_list();
free_list(&head);
exit(EXIT_SUCCESS);
}
当我尝试 运行 代码时,没有编译或 运行 时间错误,但我只得到最后一个词和一个奇怪的符号,例如:
Adding new word:Hello
Adding new word:World!
Adding new word:Does
Adding new word:my
Adding new word:code
Adding new word:work?
work?
work?
work?
work?
work?
work?
当它说添加新词的部分正确并且正确读取文件时,我的问题是打印部分。
编辑:现在我有一个正确的 EOF 检查,仍然没有按预期工作。
当您调用 add(buffer)
时,您每次都传递完全相同的指针(从技术上讲,数组不是指针,但对于本次讨论而言它足够接近)。该指针被分配给节点的 data
字段。这意味着每个节点都包含对完全相同字符串的引用。这就是为什么每个节点都打印出相同的值。此外,随着您的代码变得越来越复杂,如果 buffer
的生命周期到期,您 运行 将面临这些引用变得无效的风险。
您要做的是使用 malloc
为每个节点提供自己的字符串副本。
void add(char *data) {
size_t len = strlen(data);
node *new_node = malloc(sizeof(node)); // Note: You should check this return value.
new_node->data = malloc(len+1); // Note: Ditto.
memcpy(new_node->data, data, len+1);
new_node->next = head;
head = new_node;
printf("Adding new word:%s\n",data);
}
void free_list(ptr *hnode)
{
ptr p;
while(*hnode){
p = *hnode;
*hnode = (*hnode)->next;
free(p->data);
free(p);
}
}
在函数中添加所有节点的数据成员数据指向main中声明的同一个数组缓冲区
void add(char *data) {
node *new_node = malloc(sizeof(node));
new_node->data = data;
new_node->next = head;
head = new_node;
printf("Adding new word:%s\n",data);
}
所以函数print_list将输出缓冲区中最后存储的内容。
您需要动态复制传递的字符串。
还有这个while循环
while(i < MAX-1 && !feof(file))
{
if((ch = fgetc(file)) == ' '|| ch == '\n')
{
buffer[i] = '[=11=]';
add(buffer);
i = 0;
}
else{
buffer[i++] = ch;
}
}
没有多大意义。首先,变量 ch
应声明为类型 int
。循环中的条件
while(i < MAX-1 && !feof(file))
可能导致在缓冲区中存储值 EOF。输出证明了这一点。
(编辑:您问题中的此更新
if(ch == EOF)
break;
你是在我的回答之后做出来的。)
按一个字符读取字符串也是低效的。您应该使用函数 fscanf
而不是 fgetc
.
注意不要定义全局变量head
ptr head = NULL;
并且当某些函数依赖于全局变量时。
此外,在程序的某些部分中,您使用的是 typedef 名称 ptr
,而在程序的其他部分中,您使用的是类型 node *
。这只会让代码的读者感到困惑。
我的任务是从文件中读取单词并分别打印每个单词。 到目前为止我得到了这个:
#define MAX 100000
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct node *ptr;
typedef struct node {
char *data;
ptr next;
} node;
ptr head = NULL;
void add(char *data) {
node *new_node = malloc(sizeof(node));
new_node->data = data;
new_node->next = head;
head = new_node;
printf("Adding new word:%s\n",data);
}
void print_list() {
node *current = head;
while (current != NULL) {
printf("%s\n", current->data);
current = current->next;
}
}
void free_list(ptr *hnode)
{
ptr p;
while(*hnode){
p = *hnode;
*hnode = (*hnode)->next;
free(p);
}
}
int main(int argc, char *argv[]) {
FILE *file;
char buffer[MAX];
char ch;
int i = 0;
if (argc != 2) {
printf("Usage: %s <file>\n", argv[0]);
exit(EXIT_FAILURE);
}
file = fopen(argv[1], "r");
if (file == NULL) {
printf("Error opening file\n");
exit(EXIT_FAILURE);
}
while(i < MAX-1 && !feof(file))
{
if((ch = fgetc(file)) == ' '|| ch == '\n')
{
buffer[i] = '[=10=]';
add(buffer);
i = 0;
}
else{
if(ch == EOF)
break;
buffer[i++] = ch;
}
}
print_list();
free_list(&head);
exit(EXIT_SUCCESS);
}
当我尝试 运行 代码时,没有编译或 运行 时间错误,但我只得到最后一个词和一个奇怪的符号,例如:
Adding new word:Hello
Adding new word:World!
Adding new word:Does
Adding new word:my
Adding new word:code
Adding new word:work?
work?
work?
work?
work?
work?
work?
当它说添加新词的部分正确并且正确读取文件时,我的问题是打印部分。 编辑:现在我有一个正确的 EOF 检查,仍然没有按预期工作。
当您调用 add(buffer)
时,您每次都传递完全相同的指针(从技术上讲,数组不是指针,但对于本次讨论而言它足够接近)。该指针被分配给节点的 data
字段。这意味着每个节点都包含对完全相同字符串的引用。这就是为什么每个节点都打印出相同的值。此外,随着您的代码变得越来越复杂,如果 buffer
的生命周期到期,您 运行 将面临这些引用变得无效的风险。
您要做的是使用 malloc
为每个节点提供自己的字符串副本。
void add(char *data) {
size_t len = strlen(data);
node *new_node = malloc(sizeof(node)); // Note: You should check this return value.
new_node->data = malloc(len+1); // Note: Ditto.
memcpy(new_node->data, data, len+1);
new_node->next = head;
head = new_node;
printf("Adding new word:%s\n",data);
}
void free_list(ptr *hnode)
{
ptr p;
while(*hnode){
p = *hnode;
*hnode = (*hnode)->next;
free(p->data);
free(p);
}
}
在函数中添加所有节点的数据成员数据指向main中声明的同一个数组缓冲区
void add(char *data) {
node *new_node = malloc(sizeof(node));
new_node->data = data;
new_node->next = head;
head = new_node;
printf("Adding new word:%s\n",data);
}
所以函数print_list将输出缓冲区中最后存储的内容。
您需要动态复制传递的字符串。
还有这个while循环
while(i < MAX-1 && !feof(file))
{
if((ch = fgetc(file)) == ' '|| ch == '\n')
{
buffer[i] = '[=11=]';
add(buffer);
i = 0;
}
else{
buffer[i++] = ch;
}
}
没有多大意义。首先,变量 ch
应声明为类型 int
。循环中的条件
while(i < MAX-1 && !feof(file))
可能导致在缓冲区中存储值 EOF。输出证明了这一点。
(编辑:您问题中的此更新
if(ch == EOF)
break;
你是在我的回答之后做出来的。)
按一个字符读取字符串也是低效的。您应该使用函数 fscanf
而不是 fgetc
.
注意不要定义全局变量head
ptr head = NULL;
并且当某些函数依赖于全局变量时。
此外,在程序的某些部分中,您使用的是 typedef 名称 ptr
,而在程序的其他部分中,您使用的是类型 node *
。这只会让代码的读者感到困惑。