我有以下C代码,它将给予程序的单词写入名为“command.txt”的文件。如果word是“quit”程序结束,否则它打印该单词并将其写入文件。但是,如果单词是“file”,它将通过使用函数getstring()获取文件第一行的第一个单词,并继续下一个循环迭代。然后在新一轮使用这个词,代码直接转到“else”-branch,并打印出来并再次将其写入文件。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void getstring(char **p) {
char string[100];
char *word = NULL;
FILE *file = fopen("command.txt", "r");
fgets(string, 100, file);
word = strtok(string," \n");
p[0] = word;
fclose(file);
}
void writetofile (char **strarr) {
FILE *file = fopen("command.txt", "a");
fprintf(file, "%s\n", strarr[0]);
fclose(file);
}
int main(void) {
char line[100];
char *word = NULL;
char *strarr[5];
char **p = NULL;
int flag = 0, i;
while (1) {
if (flag == 1) {
flag = 0;
}
else {
printf("Give string: ");
fgets(line, 100, stdin);
word = strtok(line," \n");
strarr[0] = word;
}
if (strcmp(strarr[0], "quit") == 0) {
break;
}
else if (strcmp(strarr[0], "file") == 0) {
p = strarr;
getstring(p);
flag = 1;
continue;
}
else {
printf("Text: %s\n", strarr[0]);
writetofile(strarr);
}
for (i=0; i<5; i++) {
strarr[i] = NULL;
}
}
return 0;
}
问题是:如果我输入“file”,则不会向文件写入任何内容。例如,如果我给出单词“hello”,“file”和“world”,然后退出程序,打印输出如下所示:
Give string: hello
Text: hello
Give string: file
Text: hello
Give string: world
Text: world
Give string: quit
command.txt看起来像这样:
hello
world
所以,有一个空行应该是另一个“你好”。为什么是这样?我在这里遗漏了一些明显的东西,还是因为指针的使用方式?
答案 0 :(得分:3)
一旦可能出现问题,您将在getstring()
中返回指向局部变量的指针:
void getstring(char **p) {
char string[100];
char *word = NULL;
...
word = strtok(string," \n");
p[0] = word; //word points into string[] which is a local
...
}
从getstring()
返回后,本地变量string[]
不再有效,因此稍后访问p[0]
是未定义的行为。
要解决这个问题,要么将单词复制到固定缓冲区中,要么为返回字符串分配内存。
答案 1 :(得分:0)
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
char * getstring(void);
void writetofile(char *);
char * getstring()
{
static char fileString[100];
memset( fileString, 0x00, sizeof( fileString ) );
FILE *fp = fopen("command.txt", "r");
if( NULL == fp )
{
perror( "fopen" );
strcat( fileString, "ERROR: failed to open file: command.txt for read\n" );
}
else
{
if( NULL == fgets(fileString, 100, fp) )
{ // then read error or file empty
perror( "fgets" );
strcat( fileString, "I/O error occurred\n" );
}
}
fclose(fp);
return( &fileString[0] );
}
void writetofile (char *stringToWrite)
{
FILE *fp = fopen("command.txt", "a");
if( NULL == fp )
{
perror( "fopen" );
}
else
{
fprintf(fp, "%s\n", stringToWrite);
fclose(fp);
}
}
int main()
{
char line[100];
while (1)
{
printf("Give string: ");
if( NULL == fgets(line, 100, stdin) )
{
perror( "fgets" );
}
else
{ // then successful read of string from user
if( NULL == strtok(line," \n") )
{
perror( "strtok" );
}
else
{ // else found/replaced trailing newline
if (strcmp(line, "quit") == 0)
{ // then user wants to exit pgm
break;
}
// implied else
if (strcmp(line, "file") == 0)
{ // then user wants to use first line of file.
// get/save first line from file
strcpy( line, getstring() );
printf("Text: %s", line ); // note: line already contains '\n'
// append line to file
writetofile( line );
}
else
{
printf("Text: %s\n", line );
// append line to file
writetofile( line );
}
}
}
}
return( 0 );
}