C strtok()在文本文件中到达换行符时崩溃

时间:2017-11-22 01:14:48

标签: c arrays string pointers

该程序的目标是获取输入文本文件,取出每个单词并对第一个和最后一个字母之间的字母进行加扰,然后将加扰文本写入输出文件。这是我提出的代码:

void processFile(FILE* ifp, FILE* ofp) {
    printf("Begin file processing\n");
    char istr[MAXLINE], iword[50];
    char* token;
    char delimit[] = {" \t\r\n\v\f"};
    while(fgets(istr,MAXLINE,ifp)!= NULL) {
        token = strtok(istr,delimit);
        scramble(token);
        fputs(token,ofp);
        fputs(" ", ofp);
        while(token != NULL) {
            token = strtok(NULL,delimit);
            scramble(token);
            fputs(token,ofp);
            fputs(" ",ofp);
        }
    }
    printf("End file processing\n");
} /* processFile */

void scramble(char str[50]) {
printf("\nWord Scramble Start\n");
int len = strlen(str);
printf("strlen: %d\n",len);
int i = 0;
if(len > 3) {
    int t = str[1];
    for (int k = 1; k < len - 2; k++) str[k] = str[k + 1];
    str[len - 2] = t;
    printf("str: %s\n",str);
    }
}

根据我的调试尝试,一旦程序到达换行符,似乎就会发生崩溃,即使它在此之前似乎正常工作。这看起来很奇怪,因为我确实在strtok()的分隔符中包含了换行符。非常感谢任何帮助!

1 个答案:

答案 0 :(得分:1)

每次调用时,检查是否从strtok()获得了非空令牌。

#include <stdio.h>
#include <string.h>

enum { MAXLINE = 4096 };

extern void processFile(FILE *ifp, FILE *ofp);
extern void scramble(char str[]);

void processFile(FILE *ifp, FILE *ofp)
{
    printf("Begin file processing\n");
    char istr[MAXLINE];
    char *token;
    char delimit[] = {" \t\r\n\v\f"};
    while (fgets(istr, MAXLINE, ifp) != NULL)
    {
        if ((token = strtok(istr, delimit)) != NULL)
        {
            scramble(token);
            fputs(token, ofp);
            fputs(" ", ofp);
            while ((token = strtok(NULL, delimit)) != NULL)
            {
                scramble(token);
                fputs(token, ofp);
                fputs(" ", ofp);
            }
        }
    }
    printf("End file processing\n");
}

void scramble(char str[])
{
    printf("\nWord Scramble Start\n");
    int len = strlen(str);
    printf("strlen: %d\n", len);
    if (len > 3)
    {
        int t = str[1];
        for (int k = 1; k < len - 2; k++)
            str[k] = str[k + 1];
        str[len - 2] = t;
        printf("str: %s\n", str);
    }
}

int main(void)
{
    processFile(stdin, stdout);
    return 0;
}

保存为scramble97.c。以./scramble97 < scramble97.c运行时,输出为:

Begin file processing

Word Scramble Start
strlen: 8
str: #ncludie
#ncludie 
Word Scramble Start
strlen: 9
str: <tdio.hs>
<tdio.hs> 
Word Scramble Start
strlen: 8
str: #ncludie
#ncludie 
Word Scramble Start
strlen: 10
str: <tring.hs>
<tring.hs> 
Word Scramble Start
strlen: 4
str: eunm
eunm 
Word Scramble Start
strlen: 1
{ 
Word Scramble Start
strlen: 7
str: MXLINAE
MXLINAE 
Word Scramble Start
strlen: 1
= 
Word Scramble Start
strlen: 4
str: 4906
4906 
Word Scramble Start
strlen: 2
}; 
Word Scramble Start
strlen: 6
str: eterxn
eterxn 
Word Scramble Start
strlen: 4
str: viod
viod 
Word Scramble Start

…


Word Scramble Start
strlen: 12
str: pintf("strr:
pintf("strr: 
Word Scramble Start
strlen: 6
str: %\n"s,
%\n"s, 
Word Scramble Start
strlen: 5
str: sr)t;
sr)t; 
Word Scramble Start
strlen: 1
} 
Word Scramble Start
strlen: 1
} 
Word Scramble Start
strlen: 3
int 
Word Scramble Start
strlen: 10
str: min(voida)
min(voida) 
Word Scramble Start
strlen: 1
{ 
Word Scramble Start
strlen: 18
str: pocessFile(stdinr,
pocessFile(stdinr, 
Word Scramble Start
strlen: 8
str: sdout)t;
sdout)t; 
Word Scramble Start
strlen: 6
str: rturen
rturen 
Word Scramble Start
strlen: 2
0; 
Word Scramble Start
strlen: 1
} End file processing

在摆脱大部分进度报告打印后,您可能需要处理添加换行符。请注意,我删除了几个死(未使用)变量,并从&#39;数组大小&#39;中移除了50。到scramble()函数。我也将MAXLINE设置得足够大。从标准输入读取和写入标准输出是我能想到的最简单的代码测试工具。

您可以通过其他修改来减少processFile()中的重复次数:

#include <stdio.h>
#include <string.h>

enum { MAXLINE = 4096 };

extern void processFile(FILE *ifp, FILE *ofp);
extern void scramble(char str[]);

void processFile(FILE *ifp, FILE *ofp)
{
    printf("Begin file processing\n");
    char istr[MAXLINE];
    char *token;
    char delimit[] = {" \t\r\n\v\f"};
    while (fgets(istr, MAXLINE, ifp) != NULL)
    {
        char *start = istr;
        while ((token = strtok(start, delimit)) != NULL)
        {
            scramble(token);
            fprintf(ofp, "%s ", token);
            start = NULL;
        }
        putchar('\n');
    }
    printf("End file processing\n");
}

void scramble(char str[])
{
    //printf("\nWord Scramble Start\n");
    int len = strlen(str);
    //printf("strlen: %d\n", len);
    if (len > 3)
    {
        int t = str[1];
        for (int k = 1; k < len - 2; k++)
            str[k] = str[k + 1];
        str[len - 2] = t;
        //printf("str: %s\n", str);
    }
}

int main(void)
{
    processFile(stdin, stdout);
    return 0;
}

不是重复对scramble()fputs()的调用,而是将它全部包装在一个循环中,使用fprintf()进行单个I / O操作。它确实留下了空白的空白;也有办法解决这个问题。