为什么C程序打印空行到文件?

时间:2014-11-02 17:44:22

标签: c arrays pointers file-io

我有以下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

所以,有一个空行应该是另一个“你好”。为什么是这样?我在这里遗漏了一些明显的东西,还是因为指针的使用方式?

2 个答案:

答案 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 );
}