删除标点符号并使用C语言

时间:2015-04-19 21:44:02

标签: c arrays string output character-arrays

我正在为学校编写一个程序,要求从文件中读取文本,将所有内容都大写,并删除标点符号和空格。文件" Congress.txt"包含

  (国会不得制定任何关于宗教信仰或禁止自由行使的法律;或者剥夺言论自由或新闻自由;或者人民和平集会的权利,以及向政府请愿对申诉的补救。)

它正确读入但我到目前为止删除标点符号,空格和大小写会导致垃圾字符的一些主要问题。到目前为止我的代码是:

void processFile(char line[]) {
    FILE *fp;
    int i = 0;
    char c;

    if (!(fp = fopen("congress.txt", "r"))) {
        printf("File could not be opened for input.\n");
        exit(1);
    }

    line[i] = '\0';
    fseek(fp, 0, SEEK_END);
    fseek(fp, 0, SEEK_SET);
    for (i = 0; i < MAX; ++i) {
        fscanf(fp, "%c", &line[i]);
        if (line[i] == ' ')
            i++;
        else if (ispunct((unsigned char)line[i]))
            i++;
        else if (islower((unsigned char)line[i])) {
            line[i] = toupper((unsigned char)line[i]);
            i++;
        }
        printf("%c", line[i]);
        fprintf(csis, "%c", line[i]);
    }

    fclose(fp);
}

我不知道这是否是一个问题,但我将MAX定义为272,因为该文本文件包含标点符号和空格。

我得到的输出是:

    C╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
    ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠Press any key to continue . . .

3 个答案:

答案 0 :(得分:6)

基本算法需要遵循:

while next character is not EOF
    if it is alphabetic
        save the upper case version of it in the string
null terminate the string

将C转换为:

int c;
int i = 0;

while ((c = getc(fp)) != EOF)
{
    if (isalpha(c))
        line[i++] = toupper(c);
}
line[i] = '\0';

此代码不需要使用(unsigned char)中的函数进行<ctype.h>强制转换,因为c保证包含EOF(在这种情况下它不会进入正文无论如何,转换为unsigned char的字符的值。使用char c时(例如问题中的代码中)并尝试编写toupper(c)isalpha(c)时,您只需担心演​​员表。问题是普通char可以是签名类型,因此一些字符,众所周知ÿ(y-umlaut,U + 00FF,带有DIAERESIS的LATIN SMALL LETTER),将显示为负值,并打破了对<ctype.h>函数输入的要求。此代码将尝试对已经大写的字符进行大小写转换,但这可能比第二次测试便宜。

你在打印等方面做了什么,取决于你。 csis文件流是全局范围变量;那有点(tr)icky。您应该使用换行符终止输出打印。

显示的代码容易受到缓冲区溢出的影响。如果line的长度为MAX,则可以将循环条件修改为:

while (i < MAX - 1 && (c = getc(fp)) != EOF)

如果是更好的设计,则将功能签名更改为:

void processFile(int size, char line[]) {

并声称尺寸严格为正:

    assert(size > 0);

然后循环条件变为:

while (i < size - 1 && (c = getc(fp)) != EOF)

显然,你也改变了电话:

char line[4096];

processFile(sizeof(line), line);

答案 1 :(得分:1)

在发布的代码中,没有中间处理, 所以下面的代码忽略了&#39;行[]&#39;输入参数

void processFile()
{
    FILE *fp = NULL;

    if (!(fp = fopen("congress.txt", "r")))
    {
        printf("File could not be opened for input.\n");
        exit(1);
    }

    // implied else, fopen successful

    unsigned int c; // must be integer so EOF (-1) can be recognized
    while( EOF != (c =(unsigned)fgetc(fp) ) )
    {
        if( (isalpha(c) || isblank(c) ) && !ispunct(c) ) // a...z or A...Z or space
        {
            // note toupper has no effect on upper case characters
            // note toupper has no effect on a space
            printf("%c", toupper(c));
            fprintf(csis, "%c", toupper(c));
        }
    }
    printf( "\n" );

    fclose(fp);
} // end function: processFile

答案 2 :(得分:0)

好的,我所做的就是创建了第二个字符数组。我的第一个数组读入整个文件。我创建了第二个数组,它只接受第一个数组中的字母字符,然后将它们设为大写。我的作业部分的正确和完整功能如下:

void processFile(char line[], char newline[]) {
    FILE *fp;
    int i = 0;
    int j = 0;

    if (!(fp = fopen("congress.txt", "r"))) {                 //checks file open
        printf("File could not be opened for input.\n");
        exit(1);
    }
    line[i] = '\0';
    fseek(fp, 0, SEEK_END);               //idk what they do but they make it not crash
    fseek(fp, 0, SEEK_SET);

    for (i = 0; i < MAX; ++i) {           //reads the file into the first array
        fscanf(fp, "%c", &line[i]);
    }

    for (i = 0; i < MAX; ++i) {    
        if (isalpha(line[i])){                     //if it's an alphabetical character
            newline[j] = line[i];                  //read into new array
            newline[j] = toupper(newline[j]);      //makes that letter capitalized
            j++;
        }
    }

    fclose(fp);
}

确保在创建新数组后,它将小于您定义的MAX。为了方便起见,我只计算了现在丢失的标点符号和空格(这是50)所以对于将来的“for”循环它是:

for (i = 0; i < MAX - 50; ++i)