为什么我的程序输出乱码? (语言:C)
Why is my program outputting garbage characters? (Language: C)
我有以下问题:
对于一个作业,我应该逐行读取一个 txt 文件,使每一行成为链表中的一个元素,然后以正确的顺序打印出来。
如果我正确理解调试器,我已经实现了这一点,但我的输出看起来一团糟。我怀疑 nulltermination 是错误的,但这里似乎不是这种情况(请往下看)。 Picture of the output
为了可读性,我没有写出全部代码,只写了我认为是程序的重要部分。
#include <stdlib.h>
#include <stdio.h>
typedef struct node{
struct node *p;
char* string;
}node;
char *readline(FILE *stream)
//returns reference to string, returns NULL if EOF is reached before any char was read.
//If a line is EOF terminated it will return the string to the point where EOF was reached.
{
char *string = malloc(sizeof(char));
char c;
int len = 0;
if((c = getc(stream)) == EOF) return NULL;
do{
*(string + len) = c;
len++;
realloc(string, (sizeof(char)*(len)+1));
if(c == '\n') break;
}while((c = getc(stream)) != EOF);
string[len] = '[=10=]'; //make it nullterminated
return string;
}
node *new_node(FILE* stream)
// creates a new node from a line read by the readline() function.
{
node *new = malloc(sizeof(node));
new->string = readline(stream);
new->p = NULL;
return new;
}
void tail(node *newnode, node *head)
{
node *tmp = head;
while(tmp->p != NULL)
{
tmp = tmp->p;
}
tmp->p = newnode;
}
int main()
{
FILE *moby = fopen("testtxt.txt", "r");
if(moby == NULL) perror("FILE ERROR");
node *head = new_node(moby);
node *tmp;
//constructing the list
while((tmp = new_node(moby))->string != NULL)
{
tail(tmp, head);
}
//printing the list
while(1){
printf("%s", head->string);
if(head->p == NULL) break; //end of linked list is reached
head = head->p;
}
fclose(moby);
return 0;
}
特别是以下部分似乎与我构建 'strings' 的方式有问题:
while(1){
printf("%s", head->string);
if(head->p == NULL) break; //end of linked list is reached
head = head->p;
}
我的理解是,为了让 printf 与 %s 修饰符一起工作,字符串必须以 null 结尾。我想我是通过 string[len] = '[=12=]';
实现的,从调试器向我展示的内容来看,我实现它的方式是有效的。 Screenshot of the debug.
我还让调试器将它解释为一个数组,这样我就可以看到 '\0' 字符是否在我期望的位置,就是这种情况。 Screenshot of the debug.
现在我有点不知所措,因为我找不到这个问题的其他例子,调试器似乎告诉我我正在生成正确的数据。
我希望我只是错过了一个有人能够发现的小细节。
TIA
(我用的是eclipse,win 10控制台和eclipse控制台的输出是一致的)
可能还有其他问题,但你使用的realloc
是错误的。
这里
realloc(string, (sizeof(char)*(len)+1));
您需要保存 return 值,因为那是分配的内存所在的位置。
喜欢
char* temp = realloc(string, (sizeof(char)*(len)+1));
if (temp == NULL)
{
// add error handling
}
string = temp;
与描述的问题无关:
当您希望始终将新元素添加到列表末尾时,使用指向最后一个元素的 tail
指针通常是个好主意。这将使插入速度更快,因为您不需要 while(tmp->p != NULL)
循环。
我有以下问题:
对于一个作业,我应该逐行读取一个 txt 文件,使每一行成为链表中的一个元素,然后以正确的顺序打印出来。
如果我正确理解调试器,我已经实现了这一点,但我的输出看起来一团糟。我怀疑 nulltermination 是错误的,但这里似乎不是这种情况(请往下看)。 Picture of the output
为了可读性,我没有写出全部代码,只写了我认为是程序的重要部分。
#include <stdlib.h>
#include <stdio.h>
typedef struct node{
struct node *p;
char* string;
}node;
char *readline(FILE *stream)
//returns reference to string, returns NULL if EOF is reached before any char was read.
//If a line is EOF terminated it will return the string to the point where EOF was reached.
{
char *string = malloc(sizeof(char));
char c;
int len = 0;
if((c = getc(stream)) == EOF) return NULL;
do{
*(string + len) = c;
len++;
realloc(string, (sizeof(char)*(len)+1));
if(c == '\n') break;
}while((c = getc(stream)) != EOF);
string[len] = '[=10=]'; //make it nullterminated
return string;
}
node *new_node(FILE* stream)
// creates a new node from a line read by the readline() function.
{
node *new = malloc(sizeof(node));
new->string = readline(stream);
new->p = NULL;
return new;
}
void tail(node *newnode, node *head)
{
node *tmp = head;
while(tmp->p != NULL)
{
tmp = tmp->p;
}
tmp->p = newnode;
}
int main()
{
FILE *moby = fopen("testtxt.txt", "r");
if(moby == NULL) perror("FILE ERROR");
node *head = new_node(moby);
node *tmp;
//constructing the list
while((tmp = new_node(moby))->string != NULL)
{
tail(tmp, head);
}
//printing the list
while(1){
printf("%s", head->string);
if(head->p == NULL) break; //end of linked list is reached
head = head->p;
}
fclose(moby);
return 0;
}
特别是以下部分似乎与我构建 'strings' 的方式有问题:
while(1){
printf("%s", head->string);
if(head->p == NULL) break; //end of linked list is reached
head = head->p;
}
我的理解是,为了让 printf 与 %s 修饰符一起工作,字符串必须以 null 结尾。我想我是通过 string[len] = '[=12=]';
实现的,从调试器向我展示的内容来看,我实现它的方式是有效的。 Screenshot of the debug.
我还让调试器将它解释为一个数组,这样我就可以看到 '\0' 字符是否在我期望的位置,就是这种情况。 Screenshot of the debug.
现在我有点不知所措,因为我找不到这个问题的其他例子,调试器似乎告诉我我正在生成正确的数据。
我希望我只是错过了一个有人能够发现的小细节。
TIA
(我用的是eclipse,win 10控制台和eclipse控制台的输出是一致的)
可能还有其他问题,但你使用的realloc
是错误的。
这里
realloc(string, (sizeof(char)*(len)+1));
您需要保存 return 值,因为那是分配的内存所在的位置。
喜欢
char* temp = realloc(string, (sizeof(char)*(len)+1));
if (temp == NULL)
{
// add error handling
}
string = temp;
与描述的问题无关:
当您希望始终将新元素添加到列表末尾时,使用指向最后一个元素的 tail
指针通常是个好主意。这将使插入速度更快,因为您不需要 while(tmp->p != NULL)
循环。